个人专题目录](https://www.jianshu.com/p/140e2a59db2c)
1. elasticsearch文档过滤查询结果
1.1 filter与query对比
filter
,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响;
query
,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序;
一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter;
除非是你的这些搜索条件,你希望越符合这些搜索条件的document越排在前面返回,那么这些搜索条件要放在query中;如果你不希望一些搜索条件来影响你的document排序,那么就放在filter中即可;
1.2 filter与query性能对比
filter
,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据
query
,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果.
ElasticSearch提供了一种特殊的缓存,即过滤器缓存(filter cache),用来存储过滤器的结果,被缓存的过滤器并不需要消耗过多的内存(因为它们只存储了哪些文档能与过滤器相匹配的相关信息),而且可供后续所有与之相关的查询重复使用,从而极大地提高了查询性能。
1.3 filter
POST /book-index/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"brandName": {
"value": "飞利浦",
"boost": 1
}
}
},
{
"term": {
"categoryName": {
"value": "手机",
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
}
@Override
public void filterInBoolQuery(String indexName) throws Exception {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.filter(QueryBuilders.termQuery("brandName", "飞利浦"));
queryBuilder.filter(QueryBuilders.termQuery("categoryName", "手机"));
baseQuery.builder(indexName, queryBuilder);
}
1.4 range过滤器
range过滤器允许我们将搜索范围限制在字段值给定的界限范围内。
POST /book-index/_search
{
"from": 0,
"size": 100,
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "三星",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1
}
}
}
],
"filter": [
{
"range": {
"price": {
"from": 2000,
"to": 3000,
"include_lower": true,
"include_upper": true,
"boost": 1
}
}
}
],
"must_not": [
{
"term": {
"brandName": {
"value": "诺基亚",
"boost": 1
}
}
}
],
"should": [
{
"term": {
"categoryName": {
"value": "手机",
"boost": 1
}
}
},
{
"term": {
"categoryName": {
"value": "平板电视",
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
}
@Override
public void rangeQuery(String indexName, String fieldName, int from, int to) throws Exception {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.should(QueryBuilders.termQuery("categoryName", "手机"));
queryBuilder.should(QueryBuilders.termQuery("categoryName", "平板电视"));
queryBuilder.must(QueryBuilders.matchQuery("title", "三星"));
queryBuilder.mustNot(QueryBuilders.termQuery("brandName", "诺基亚"));
queryBuilder.filter(QueryBuilders.rangeQuery(fieldName).from(from).to(to));
baseQuery.builder(indexName, queryBuilder);
}
@Test
public void testRangeCardQuery() throws Exception {
filterQuery.rangeQuery(indexName,"price",1,5);
}
1.5 exists 过滤器
exists 过滤器只选择给定字段的文档。如果某字段没有值,就不选择。
比如我们查询响应时间不为空的文档:
POST /book-index/_search
{
"query": {
"exists": {
"field": "title",
"boost": 1
}
}
}
@Override
public void existQuery(String indexName, String fieldName) throws Exception {
baseQuery.builder(indexName, QueryBuilders.existsQuery(fieldName));
}
@Test
public void testExistQuery() throws IOException {
Goods goods = new Goods();
goods.setId(1);
//goods.setTitle("new2 - 阿尔卡特 (OT-927) 炭黑 联通3G手机 双卡双待");
goods.setPrice(22.32);
goods.setStock(23232);
goods.setSaleNum(32);
goods.setCreateTime(new Date());
goods.setCategoryName("平板电视");
goods.setBrandName("三星");
goods.setSpecStr("{\"电视屏幕尺寸\":\"46英寸\"}");
docService.addDoc(Constants.INDEX_NAME, objectMapper.writeValueAsString(goods), "1");
filterQuery.existQuery(Constants.INDEX_NAME, "title");
}
网友评论