我正在使用 ElasticSearch 1.5.2。
在 Java 中,我编写如下查询:
public QueryBuilder composeQuery(
String brand,
String product,
/** inclusive, nullable */
Instant start,
/** inclusive, nullable */
Instant end
) {
final QueryBuilder nominalQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("brand", brand))
.must(QueryBuilders.matchQuery("product", product));
final QueryBuilder withRangeApplied;
if (start == null && end == null) {
withRangeApplied = nominalQuery;
} else {
final RangeFilterBuilder rangeFilter
= FilterBuilders.rangeFilter("timestamp");
rangeFilter.gte(start);
rangeFilter.lte(end);
withRangeApplied = QueryBuilders.filteredQuery(
nominalQuery,
rangeFilter);
}
return withRangeApplied;
}
但我不喜欢我必须做这个空检查。随着产品的发展,我们的代码库中会包含很多这样的内容。我宁愿让所有代码都走同一条路,如下所示:
public QueryBuilder composeQuery(
String brand,
String product,
/** inclusive, nullable */
Instant start,
/** inclusive, nullable */
Instant end
) {
final QueryBuilder nominalQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("brand", brand))
.must(QueryBuilders.matchQuery("product", product));
final RangeFilterBuilder rangeFilter
= FilterBuilders.rangeFilter("timestamp");
rangeFilter.gte(start);
rangeFilter.lte(end);
return QueryBuilders.filteredQuery(
nominalQuery,
rangeFilter);
}
这意味着我们不必要地将{ start: null, end: null }范围过滤器强加给我们的查询。这是否会为 ElasticSearch 带来额外的工作?
我使用 Profile API(在具有类似索引和映射的空 ES 2.4.1 数据库上——这不是一个公平的测试,但我唯一可用的资源)来询问有关查询的一些问题。
{ start: null, end: null }在查询计划中显示为:
{
query_type: "MultiTermQueryConstantScoreWrapper",
lucene: "timestamp:[* TO *]",
time: "0.0003ms",
breakdown: {
create_weight: 344
}
}
那个时间比我的任何一个“TermQuery”元素都小一个数量级。这向我表明这是一个相对便宜的过滤器。然而,“非空过滤器”具有完全相同的、微小的时间成本。所以我不相信这是一个无操作。
这个“空过滤器”的存在并没有增加重写时间(与“无过滤器”相比)。
而“非空过滤器”的重写时间是“空过滤器”或“空过滤器”的两倍。
从这些结果:我被引导相信与“无过滤器”相比,“空过滤器”增加的工作量可以忽略不计(事实上,与“非空过滤器”增加的成本相同,可以忽略不计)。有人可以更确定地确认这种无操作过滤器很便宜(或已优化)吗?