我正在使用 elasticSearch 来查找系列中的下一集。为此,我首先过滤比上一集更高season
或更高episode
的剧集,然后season
按episode
升序排序,并将结果限制为 1:
...
FilterBuilder sameSeriesFilter = termsFilter("tvShowId", previousEpisode.getTvShowId());
FilterBuilder greaterEpisodeFilter = rangeFilter("episode").gt(previousEpisode.getEpisode());
FilterBuilder greaterSeasonFilter = rangeFilter("season").gt(previousEpisode.getSeason());
List<Sort.Field> sortFields = Arrays.asList(new Sort.Field("season", Sort.Order.ASC),new Sort.Field("episode", Sort.Order.ASC));
Sort episodeSort = new Sort(sortFields);
AndFilterBuilder filter = FilterBuilders.andFilter(
sameSeriesFilter,
orFilter(
greaterEpisodeFilter,
greaterSeasonFilter
)
);
String query = filter.toString(); //here for debugging purposes
return client.getItems(GetItems
.<Asset>newBuilder()
.index(index)
.filter(filter)
.sort(episodeSort)
.page(1,1)
.type(ASSET)
.tClass(Asset.class)
.build()
);
}).map(assetHitList ->
assetHitList.getHits().isEmpty() ? null : assetHitList.getHits().get(0)) ;
}
在运行时将过滤器提取为字符串会给我以下查询:
{
"and" : {
"filters" : [ {
"terms" : {
"tvShowId" : [ "breaking-bad" ]
}
},{
"or" : {
"filters" : [ {
"range" : {
"episode" : {
"from" : 1,
"to" : null,
"include_lower" : false,
"include_upper" : true
}
}
}, {
"range" : {
"season" : {
"from" : 2,
"to" : null,
"include_lower" : false,
"include_upper" : true
}
}
} ]
}
} ]
}
}
这令人困惑地导致:
{
"assetId" : "breaking-bad-s01-e1_foobar",
"tvShowId" : "breaking-bad"
"episode" : "1",
"season" : "1",
"originalTitle" : "Dummy breaking-bad-s01-e1_foobar",
}
(为简洁起见,删除了一些字段)
请注意,episode
结果season
都是 1,即使过滤器指定(我认为)其中一个必须分别高于 2 和 1。
我还尝试反转排序,而是降序排序,这导致了一个完全不同系列的剧集,所以似乎sameSeriesFilter
也没有应用,但是排序似乎有效!
无论如何...这里发生了什么?
更新:忘了提,这是 ES 的 v.1.7。
我已经设法让它工作了,但是发生了一些神秘的事情。一时兴起,我添加了一个空的 matchAll 查询,它应该什么都不做,但由于某种原因使一切正常。我的过滤器现在已正确应用。ES应该这样工作吗?如果是这样,为什么?新的工作代码:
return client.getItems(GetItems
.<Asset>newBuilder()
.index(index)
.matchAllQuery() //<--this made it work!?!
.filter(filter)
.sort(episodeSort)
.page(1,1)
.type(ASSET)
.tClass(Asset.class)
.build()
);