Elasticsearch:如何在搜索中实现 should_not 过滤器
2020-09-01 18:19
821 查看
在 Elasticsearch 中,我们可以使用 bool query 来说实现一种组合的查询。它可以具有如下的一种形式的搜索:
[code]POST _search { "query": { "bool" : { "must" : { "term" : { "user.id" : "kimchy" } }, "filter": { "term" : { "tags" : "production" } }, "must_not" : { "range" : { "age" : { "gte" : 10, "lte" : 20 } } }, "should" : [ { "term" : { "tags" : "env1" } }, { "term" : { "tags" : "deployed" } } ], "minimum_should_match" : 1, "boost" : 1.0 } } }
在上面,我看到了 must 和 must_not 这样的组合,他们表示必须满足以及禁止满足的意思。我们也同时看到了 should 这个 clause,它表示如果满足就可以增加分数,但是我们看到没有 should_not 这样的表达方法。在我们的实际的搜索中这个其实也是蛮有用的,比如我想对某些不满足一定条件的查询进行加分。
在今天的文章中,我们用一个例子来展示如何实现 shoud_not 这样的查询。
我们首先以我们之前的用过的数据来进行展示:
[code]POST _bulk { "index" : { "_index" : "twitter", "_id": 1} } {"user":"双榆树-张三","message":"今儿天气不错啊,出去转转去","uid":2,"age":20,"city":"北京","province":"北京","country":"中国","address":"中国北京市海淀区","location":{"lat":"39.970718","lon":"116.325747"}} { "index" : { "_index" : "twitter", "_id": 2 }} {"user":"东城区-老刘","message":"出发,下一站云南!","uid":3,"age":30,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区台基厂三条3号","location":{"lat":"39.904313","lon":"116.412754"}} { "index" : { "_index" : "twitter", "_id": 3} } {"user":"东城区-李四","message":"happy birthday!","uid":4,"age":30,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区","location":{"lat":"39.893801","lon":"116.408986"}} { "index" : { "_index" : "twitter", "_id": 4} } {"user":"朝阳区-老贾","message":"123,gogogo","uid":5,"age":35,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区建国门","location":{"lat":"39.718256","lon":"116.367910"}} { "index" : { "_index" : "twitter", "_id": 5} } {"user":"朝阳区-老王","message":"Happy BirthDay My Friend!","uid":6,"age":50,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区国贸","location":{"lat":"39.918256","lon":"116.467910"}} { "index" : { "_index" : "twitter", "_id": 6} } {"user":"虹桥-老吴","message":"好友来了都今天我生日,好友来了,什么 birthday happy 就成!","uid":7,"age":90,"city":"上海","province":"上海","country":"中国","address":"中国上海市闵行区","location":{"lat":"31.175927","lon":"121.383328"}}
打入上面的 _bulk 指令,我们就创建了一个叫做 twitter 的索引。
我们首先来测试如下的搜索:
[code]GET twitter/_search { "query": { "bool": { "must": [ { "range": { "age": { "gte": 40 } } } ], "should": [ { "match": { "city": "上海" } } ] } } }
上面的搜索表示的意思是:搜索出年龄大于40岁的文档,而且来自上海的文档的排名靠前。搜索的结果就是:
[code]{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 2.5404449, "hits" : [ { "_index" : "twitter", "_type" : "_doc", "_id" : "6", "_score" : 2.5404449, "_source" : { "user" : "虹桥-老吴", "message" : "好友来了都今天我生日,好友来了,什么 birthday happy 就成!", "uid" : 7, "age" : 90, "city" : "上海", "province" : "上海", "country" : "中国", "address" : "中国上海市闵行区", "location" : { "lat" : "31.175927", "lon" : "121.383328" } } }, { "_index" : "twitter", "_type" : "_doc", "_id" : "5", "_score" : 1.0, "_source" : { "user" : "朝阳区-老王", "message" : "Happy BirthDay My Friend!", "uid" : 6, "age" : 50, "city" : "北京", "province" : "北京", "country" : "中国", "address" : "中国北京市朝阳区国贸", "location" : { "lat" : "39.918256", "lon" : "116.467910" } } } ] } }
从上面的搜索的结果,我们可以看出来 _id 为 6 的来自上海的文档排名靠前。
假如现在我们的问题变为:我们想搜索年龄大于49岁,但是不来自上海的排名得分靠前,我们该如何实现这个目的呢?按照这个要求,我们实现如下的 should_not 方法:
[code]GET twitter/_search { "query": { "bool": { "must": [ { "range": { "age": { "gte": 40 } } } ], "should": [ { "bool": { "must_not": [ { "match": { "city": "上海" } } ] } } ] } } }
请注意上面的 should 部分的写法。它使用了另外一个 bool query 来表达一个来自非上海的查询。上面的查询的结果是:
[code]{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "twitter", "_type" : "_doc", "_id" : "5", "_score" : 1.0, "_source" : { "user" : "朝阳区-老王", "message" : "Happy BirthDay My Friend!", "uid" : 6, "age" : 50, "city" : "北京", "province" : "北京", "country" : "中国", "address" : "中国北京市朝阳区国贸", "location" : { "lat" : "39.918256", "lon" : "116.467910" } } }, { "_index" : "twitter", "_type" : "_doc", "_id" : "6", "_score" : 1.0, "_source" : { "user" : "虹桥-老吴", "message" : "好友来了都今天我生日,好友来了,什么 birthday happy 就成!", "uid" : 7, "age" : 90, "city" : "上海", "province" : "上海", "country" : "中国", "address" : "中国上海市闵行区", "location" : { "lat" : "31.175927", "lon" : "121.383328" } } } ] } }
显然这次的结果,我们并没有改变所返回的数据的数量,但是我们确实改变了返回数据的次序,虽然在本例子中分数还是 1.0(这是因为 must_not 不影响分数)。在这次的查询中,我们可以看到来自北京的文档的排名提前了。
相关文章推荐
- 站内搜索关键词功能如何实现
- 如何通过程序实现搜索帮助
- Elasticsearch1.x 基于lc-pinyin和ik分词实现 中文、拼音、同义词搜索
- 如何用SQL语句实现精确搜索以及模糊搜索
- sharepoint 2013 在office 365中 如何嵌入JS代码实现搜索功能
- elasticsearch 在不是 not_analyzed 的前提下如何全匹配的效果
- Elasticsearch:如何使用正确的姿势进行搜索
- 如何用SQL语句实现精确搜索以及模糊搜索
- 分布式搜索elasticsearch java API 之(八)------使用More like this实现基于内容的推荐
- 如何实现按下回车键实现搜索
- iOS- 本地文本容错搜索引擎2-->如何实现英文(英文首字母,汉语拼音)对中文的搜索?
- elasticsearch2.1.1实现范围搜索
- Lucene.Net如何实现搜索结果分类统计功能
- 如何实现IOS_SearchBar搜索栏及关键字高亮
- 如何实现拼音搜索
- 将搜索结果排在前面,其余信息顺序排在后面,用SQL如何实现
- 动易系统如何实现按频道搜索的功能
- jQuery : 如何用 contains 过滤器来实现精确匹配
- ORACLE如何使用模糊查询(如何实现关键字搜索)
- 在项目中,过滤器如何配置?可以实现拦截!