往往为了利于检索,solr的schema中会有大量的字段,但是提交到客户端并不会把所有的字段信息都返回,这时候只会投影部分字段信息。
例如,完整的结构如下:
"data": [
{
"resId": "1713074",
"musicId": "1462975",
"musicName": "말해버리면 (如果说出来的话)",
"areaName": "其他",
"typeId": 4,
"typeName": "MV",
"singerName": "안녕의 온도",
"listenNumber": 438,
"singerTypeName": "未知",
"publicTime": "2018-5-8",
"resName": "말해버리면 (如果说出来的话)",
"resNamePy": "말해버리면 (RGSCLDH)",
"resSingerPy": "안녕의 온도(WHDWD)",
"picture": "http://puui.qpic.cn/qqvideo_ori/0/g0026pq44za_496_280/0",
"tags": "地区,主题,年代,2018",
"keywords": [
"말해버리면 (如果说出来的话)",
"其他",
"MV",
"안녕의 온도",
"未知",
"2018-5-8",
"地区,主题,年代,2018"
]
}
],
但是我们只想返回给客户端:
"data": [
{
"musicId": "1462975",
"musicName": "말해버리면 (如果说出来的话)",
"typeId": 4,
"singerName": "안녕의 온도",
"publicTime": "2018-5-8",
"picture": "http://puui.qpic.cn/qqvideo_ori/0/g0026pq44za_496_280/0",
}
],
这时就需要用到投影(projection)了。
投影
CustomMusicRepository接口中增加:
public ScoredPage searchByNameProjection(String searchName, long pageIndex, int pageSize);
MusicRepositoryImpl实现:
@Override
public ScoredPage searchByNameProjection(String searchName, long pageIndex, int pageSize) {
String[] words = searchName.toUpperCase().split(" ");
String[] contidionFields = new String[]{Music.FIELD_SONG_NAME, Music.FIELD_SINGER_NAME};
Criteria conditions = createSearchConditions(contidionFields, words);
SimpleQuery search = new SimpleQuery(conditions);
// 投影
search.addProjectionOnField(Music.FIELD_SONG_NAME);
search.setOffset(pageIndex);
search.setRows(pageSize);
ScoredPage page = solrTemplate.queryForPage(Music.CORE_NAME, search, Music.class);
return page;
}
以上代码将songName加入到投影中,那么输出就只有songName才会有值,其余字段均为null。
测试代码:
@Test
public void searchByNameProjection() {
ScoredPage musicList = musicRepository.searchByNameProjection("刘德华", 0, 10);
for (Music music : musicList.getContent()) {
System.out.println(music);
}
}
结果如下:
com.ali.model.Music@64a8c844[resId=,songId=,songName=《追龙》持续超车 刘德华身兼化妆师搬运工,singerName=,keywords=]
com.ali.model.Music@3f6db3fb[resId=,songId=,songName=情深的一句,singerName=,keywords=]
com.ali.model.Music@52de51b6[resId=,songId=,songName=无心快意,singerName=,keywords=]
com.ali.model.Music@18c5069b[resId=,songId=,songName=刘德华,singerName=,keywords=]
排序
排序比较简单,将上面的方法改造一下,加入排序:
@Override
public ScoredPage searchByNameProjection(String searchName, long pageIndex, int pageSize) {
String[] words = searchName.toUpperCase().split(" ");
String[] contidionFields = new String[]{Music.FIELD_SONG_NAME, Music.FIELD_SINGER_NAME};
Criteria conditions = createSearchConditions(contidionFields, words);
SimpleQuery search = new SimpleQuery(conditions);
Sort sort = new Sort(Sort.Direction.DESC, Music.FIELD_SONG_ID);
search.addSort(sort);
search.addProjectionOnField(Music.FIELD_SONG_NAME);
search.setOffset(pageIndex);
search.setRows(pageSize);
ScoredPage page = solrTemplate.queryForPage(Music.CORE_NAME, search, Music.class);
return page;
}
执行上面代码,返回结果即会按照songId 倒序排列。