带排除OR的嵌套过滤器查询 [英] Nested Filter Query with Exclusionary ORs
问题描述
我无法将结果集限制为符合 kol_tags.scored.name
和 kol_tags.scored.score $ c的文档$ c>范围为
或
选项。
I am unable to restrict the result set to documents that match both kol_tags.scored.name
and kol_tags.scored.score
range for both the or
options below.
我想匹配Core Grower和<$$的$ code> kol_tags.scored.name c $ c> kol_tags.scored.score 介于1到100之间,除非它们还具有 kol_tags.scored.name
的连接,其中 kol_tags.scored.score
是不,范围为35至65。
I would like to match documents that have the kol_tags.scored.name
of "Core Grower" and kol_tags.scored.score
between 1 and 100 unless they also have kol_tags.scored.name
of "Connectivity" where kol_tags.scored.score
is NOT in the range of 35 to 65.
给定以下内容映射(为简洁起见省略了非嵌套字段):
Given the following mapping (non nested fields omitted for brevity):
GET /production_users/user/_mapping
{
"user": {
"_all": {
"enabled": false
},
"properties": {
"kol_tags": {
"type": "nested",
"properties": {
"scored": {
"type": "nested",
"properties": {
"name": {
"type": "string",
"index": "not_analyzed",
"omit_norms": true,
"index_options": "docs"
},
"score": {
"type": "integer"
}
}
}
}
}
}
}
}
我正在执行以下查询: p>
I am executing the following query:
{
"filter": {
"nested": {
"path": "kol_tags.scored",
"filter": {
"or": [
{
"and": [
{
"terms": {
"kol_tags.scored.name": [
"Core Grower"
]
}
},
{
"range": {
"kol_tags.scored.score": {
"gte": 1,
"lte": 100
}
}
}
]
},
{
"and": [
{
"terms": {
"kol_tags.scored.name": [
"Connectivity"
]
}
},
{
"range": {
"kol_tags.scored.score": {
"gte": 35,
"lte": 65
}
}
}
]
}
]
}
}
}
}
使用上面的查询,我获得了符合 kol_tags.scored.name的文档Core Grower的
和 kol_tags.scored.score
1到100之间, ALSO 有 kol_tags.scored.name
的连接和 kol_tags.scored.score
在任何范围内。
With the query above I get documents that match kol_tags.scored.name
of "Core Grower" and kol_tags.scored.score
between 1 and 100 and ALSO that have kol_tags.scored.name
of "Connectivity" and kol_tags.scored.score
in any range.
我需要的是匹配的文件:
What I need is documents that match:
-
Core Grower的kol_tags.scored.name
和kol_tags.scored.score
1到100之间 - 排除具有连接和
kol_tags.scored.score的
小于34且大于66kol_tags.scored.name
的任何文档
< 连接和
kol_tags.scored.score
35和65之间的 kol_tags.scored.name
kol_tags.scored.name
of "Core Grower" andkol_tags.scored.score
between 1 and 100kol_tags.scored.name
of "Connectivity" andkol_tags.scored.score
between 35 and 65- Exclude any documents that have
kol_tags.scored.name
of "Connectivity" andkol_tags.scored.score
less than 34 and greater than 66
推荐答案
您的描述有一些歧义,但我试图制作一个可运行的例子,应该在这里工作: https://www.found.no/play/gist/8940202 (也嵌入下面)
There's some ambiguity in your description, but I've tried to make a runnable example that should work here: https://www.found.no/play/gist/8940202 (also embedded below)
以下是我所做的一些事情:
Here's a few things I did:
-
将过滤器置于
过滤的
-query中。只有当您想要过滤匹配时,才应使用顶级过滤器
(重命名为Elasticsearch 1.0中的post_filter
)
Put the filter in a
filtered
-query. A top levelfilter
(renamed topost_filter
in Elasticsearch 1.0) should only be used if you want to filter hits, but not facets.
使用 bool
而不是和
和或
,因为过滤器是可高速缓存的。更多这里: http://www.elasticsearch.org/blog/all -about-elasticsearch-filter-bitsets /
Use bool
instead of and
and or
, since the filters are cachable. More here: http://www.elasticsearch.org/blog/all-about-elasticsearch-filter-bitsets/
最重要的是,将嵌套
bool
,所以逻辑正确wrt。嵌套和父文档应该匹配什么。
And most importantly, put the nested
inside the bool
, so the logic gets right wrt. what should match on the nested vs. the parent document.
添加了一个 must_not
最后一点。不确定是否可以有两个名称为连接
的子文档,但如果可以的话,那应该是这样的。如果你只有一个,你可以删除 must_not
。
Added a must_not
to account for your last point. Not sure if you can have two sub-documents with name "Connectivity"
, but if you can, that should account for it. If you'll only ever have one, you can remove the must_not
.
您没有提供任何示例文档,所以我想一些我认为应该适合您的描述。我不认为你需要两个级别的嵌套。
You didn't provide any sample documents, so I made some I think should fit your description. I don't think you need two levels of nested.
#!/bin/bash
export ELASTICSEARCH_ENDPOINT="http://localhost:9200"
# Create indexes
curl -XPUT "$ELASTICSEARCH_ENDPOINT/play" -d '{
"mappings": {
"type": {
"properties": {
"kol_tags": {
"properties": {
"scored": {
"type": "nested",
"properties": {
"name": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
}
}
}'
# Index documents
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d '
{"index":{"_index":"play","_type":"type"}}
{"kol_tags":{"scored":[{"name":"Core Grower","score":36},{"name":"Connectivity","score":42}]}}
{"index":{"_index":"play","_type":"type"}}
{"kol_tags":{"scored":[{"name":"Connectivity","score":34},{"name":"Connectivity","score":42}]}}
{"index":{"_index":"play","_type":"type"}}
{"kol_tags":{"scored":[{"name":"Core Grower","score":36}]}}
{"index":{"_index":"play","_type":"type"}}
{"kol_tags":{"scored":[{"name":"Connectivity","score":36}]}}
'
# Do searches
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"nested": {
"path": "kol_tags.scored",
"filter": {
"bool": {
"must": [
{
"term": {
"name": "Core Grower"
}
},
{
"range": {
"score": {
"gte": 1,
"lte": 100
}
}
}
]
}
}
}
},
{
"nested": {
"path": "kol_tags.scored",
"filter": {
"bool": {
"must": [
{
"term": {
"name": "Connectivity"
}
},
{
"range": {
"score": {
"gte": 35,
"lte": 65
}
}
}
]
}
}
}
}
],
"must_not": [
{
"nested": {
"path": "kol_tags.scored",
"filter": {
"bool": {
"must": [
{
"term": {
"name": "Connectivity"
}
},
{
"not": {
"range": {
"score": {
"gte": 35,
"lte": 65
}
}
}
}
]
}
}
}
}
]
}
}
}
}
}
'
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
"filter": {
"nested": {
"path": "kol_tags.scored",
"filter": {
"or": [
{
"and": [
{
"terms": {
"kol_tags.scored.name": [
"Core Grower"
]
}
},
{
"range": {
"kol_tags.scored.score": {
"gte": 1,
"lte": 100
}
}
}
]
},
{
"and": [
{
"terms": {
"kol_tags.scored.name": [
"Connectivity"
]
}
},
{
"range": {
"kol_tags.scored.score": {
"gte": 35,
"lte": 65
}
}
}
]
}
]
}
}
}
}
'
这篇关于带排除OR的嵌套过滤器查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!