Elasticsearch 按数组字段中的对象中的多个字段进行过滤
Elasticsearch filter by multiple fields in an object which is in an array field
目标是过滤具有多个价格的产品。
数据如下所示:
{
"name":"a",
"price":[
{
"membershipLevel":"Gold",
"price":"5"
},
{
"membershipLevel":"Silver",
"price":"50"
},
{
"membershipLevel":"Bronze",
"price":"100"
}
]
}
我想按 membershipLevel
和 price
过滤。 比如如果我是白银会员,查询价格区间0-10,应该不会出现该商品,如果我是金卡会员,应该会出现商品"a" . Elasticsearch支持这种查询吗?
您必须使用嵌套字段和嵌套查询来存档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
定义类型为 "Nested" 的价格 属性,然后您将能够按每个 属性 嵌套对象
进行过滤
让我向您展示如何使用 nested fields and query and filter context。我将以您的示例向您展示如何定义索引映射、索引示例文档和搜索查询。
需要注意的是Elasticsearch映射中的include_in_parent
参数,它允许我们在不使用嵌套字段的情况下使用这些嵌套字段。
请参考Elasticsearch文档。
If true, all fields in the nested object are also added to the parent
document as standard (flat) fields. Defaults to false.
索引定义
{
"mappings": {
"properties": {
"product": {
"type": "nested",
"include_in_parent": true
}
}
}
}
索引示例文档
{
"product": {
"price" : 5,
"membershipLevel" : "Gold"
}
}
{
"product": {
"price" : 50,
"membershipLevel" : "Silver"
}
}
{
"product": {
"price" : 100,
"membershipLevel" : "Bronze"
}
}
搜索查询以显示价格范围为 0-10
的 Gold
{
"query": {
"bool": {
"must": [
{
"match": {
"product.membershipLevel": "Gold"
}
}
],
"filter": [
{
"range": {
"product.price": {
"gte": 0,
"lte" : 10
}
}
}
]
}
}
}
结果
"hits": [
{
"_index": "so-60620921-nested",
"_type": "_doc",
"_id": "1",
"_score": 1.0296195,
"_source": {
"product": {
"price": 5,
"membershipLevel": "Gold"
}
}
}
]
要排除的搜索查询 Silver
,价格范围相同
{
"query": {
"bool": {
"must": [
{
"match": {
"product.membershipLevel": "Silver"
}
}
],
"filter": [
{
"range": {
"product.price": {
"gte": 0,
"lte" : 10
}
}
}
]
}
}
}
以上查询没有 return 任何结果,因为没有任何匹配结果。
P.S :- 所以答案可能会帮助您了解嵌套字段并详细查询它们。
您需要为您的用例使用 nested
datatype for price
and make use of nested query
。
请参阅以下映射、示例文档、查询和响应:
映射:
PUT my_price_index
{
"mappings": {
"properties": {
"name":{
"type":"text"
},
"price":{
"type":"nested",
"properties": {
"membershipLevel":{
"type":"keyword"
},
"price":{
"type":"double"
}
}
}
}
}
}
示例文档:
POST my_price_index/_doc/1
{
"name":"a",
"price":[
{
"membershipLevel":"Gold",
"price":"5"
},
{
"membershipLevel":"Silver",
"price":"50"
},
{
"membershipLevel":"Bronze",
"price":"100"
}
]
}
查询:
POST my_price_index/_search
{
"query": {
"nested": {
"path": "price",
"query": {
"bool": {
"must": [
{
"term": {
"price.membershipLevel": "Gold"
}
},
{
"range": {
"price.price": {
"gte": 0,
"lte": 10
}
}
}
]
}
},
"inner_hits": {} <---- Do note this.
}
}
}
上述查询的意思是,我想return price.price
范围从0 to 10
到price.membershipLevel
的所有文档为Gold
。
请注意,我使用了 inner_hits
。原因是尽管是嵌套文档,作为响应的 ES 将 return 整个文档集,而不仅仅是特定于查询子句适用位置的文档。
为了找到匹配的确切嵌套文档,您需要使用 inner_hits
。
以下是响应方式 return。
回复:
{
"took" : 128,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.9808291,
"hits" : [
{
"_index" : "my_price_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.9808291,
"_source" : {
"name" : "a",
"price" : [
{
"membershipLevel" : "Gold",
"price" : "5"
},
{
"membershipLevel" : "Silver",
"price" : "50"
},
{
"membershipLevel" : "Bronze",
"price" : "100"
}
]
},
"inner_hits" : {
"price" : {
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.9808291,
"hits" : [
{
"_index" : "my_price_index",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "price",
"offset" : 0
},
"_score" : 1.9808291,
"_source" : {
"membershipLevel" : "Gold",
"price" : "5"
}
}
]
}
}
}
}
]
}
}
希望对您有所帮助!
目标是过滤具有多个价格的产品。
数据如下所示:
{
"name":"a",
"price":[
{
"membershipLevel":"Gold",
"price":"5"
},
{
"membershipLevel":"Silver",
"price":"50"
},
{
"membershipLevel":"Bronze",
"price":"100"
}
]
}
我想按 membershipLevel
和 price
过滤。 比如如果我是白银会员,查询价格区间0-10,应该不会出现该商品,如果我是金卡会员,应该会出现商品"a" . Elasticsearch支持这种查询吗?
您必须使用嵌套字段和嵌套查询来存档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
定义类型为 "Nested" 的价格 属性,然后您将能够按每个 属性 嵌套对象
进行过滤让我向您展示如何使用 nested fields and query and filter context。我将以您的示例向您展示如何定义索引映射、索引示例文档和搜索查询。
需要注意的是Elasticsearch映射中的include_in_parent
参数,它允许我们在不使用嵌套字段的情况下使用这些嵌套字段。
请参考Elasticsearch文档。
If true, all fields in the nested object are also added to the parent document as standard (flat) fields. Defaults to false.
索引定义
{
"mappings": {
"properties": {
"product": {
"type": "nested",
"include_in_parent": true
}
}
}
}
索引示例文档
{
"product": {
"price" : 5,
"membershipLevel" : "Gold"
}
}
{
"product": {
"price" : 50,
"membershipLevel" : "Silver"
}
}
{
"product": {
"price" : 100,
"membershipLevel" : "Bronze"
}
}
搜索查询以显示价格范围为 0-10
的Gold
{
"query": {
"bool": {
"must": [
{
"match": {
"product.membershipLevel": "Gold"
}
}
],
"filter": [
{
"range": {
"product.price": {
"gte": 0,
"lte" : 10
}
}
}
]
}
}
}
结果
"hits": [
{
"_index": "so-60620921-nested",
"_type": "_doc",
"_id": "1",
"_score": 1.0296195,
"_source": {
"product": {
"price": 5,
"membershipLevel": "Gold"
}
}
}
]
要排除的搜索查询 Silver
,价格范围相同
{
"query": {
"bool": {
"must": [
{
"match": {
"product.membershipLevel": "Silver"
}
}
],
"filter": [
{
"range": {
"product.price": {
"gte": 0,
"lte" : 10
}
}
}
]
}
}
}
以上查询没有 return 任何结果,因为没有任何匹配结果。
P.S :-
您需要为您的用例使用 nested
datatype for price
and make use of nested query
。
请参阅以下映射、示例文档、查询和响应:
映射:
PUT my_price_index
{
"mappings": {
"properties": {
"name":{
"type":"text"
},
"price":{
"type":"nested",
"properties": {
"membershipLevel":{
"type":"keyword"
},
"price":{
"type":"double"
}
}
}
}
}
}
示例文档:
POST my_price_index/_doc/1
{
"name":"a",
"price":[
{
"membershipLevel":"Gold",
"price":"5"
},
{
"membershipLevel":"Silver",
"price":"50"
},
{
"membershipLevel":"Bronze",
"price":"100"
}
]
}
查询:
POST my_price_index/_search
{
"query": {
"nested": {
"path": "price",
"query": {
"bool": {
"must": [
{
"term": {
"price.membershipLevel": "Gold"
}
},
{
"range": {
"price.price": {
"gte": 0,
"lte": 10
}
}
}
]
}
},
"inner_hits": {} <---- Do note this.
}
}
}
上述查询的意思是,我想return price.price
范围从0 to 10
到price.membershipLevel
的所有文档为Gold
。
请注意,我使用了 inner_hits
。原因是尽管是嵌套文档,作为响应的 ES 将 return 整个文档集,而不仅仅是特定于查询子句适用位置的文档。
为了找到匹配的确切嵌套文档,您需要使用 inner_hits
。
以下是响应方式 return。
回复:
{
"took" : 128,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.9808291,
"hits" : [
{
"_index" : "my_price_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.9808291,
"_source" : {
"name" : "a",
"price" : [
{
"membershipLevel" : "Gold",
"price" : "5"
},
{
"membershipLevel" : "Silver",
"price" : "50"
},
{
"membershipLevel" : "Bronze",
"price" : "100"
}
]
},
"inner_hits" : {
"price" : {
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.9808291,
"hits" : [
{
"_index" : "my_price_index",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "price",
"offset" : 0
},
"_score" : 1.9808291,
"_source" : {
"membershipLevel" : "Gold",
"price" : "5"
}
}
]
}
}
}
}
]
}
}
希望对您有所帮助!