弹性搜索响应中嵌套对象的条件源过滤

问题描述 投票:0回答:1

我有一个具有以下(简化)结构的文档索引。

{
  "product_id": "abc123",
  "properties": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}

每个文档可以有数百个属性。

现在 - 我希望能够搜索与查询匹配的文档,还可以指定返回时应填充每个文档的属性。所以基本上我想写下面的请求:

获取与查询x匹配的所有文档,并使用属性[“height”,“width”,“foobar”]填充每个文档。

具有我想要返回的属性的数组是在查询时根据用户的输入创建的。对查询的响应中的文档如下所示:

{
  "product_id": "abc123",
  "properties": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    }
    // No depth!
  ]
}

我试图通过源过滤实现这一点无济于事。我怀疑脚本字段可能是解决这个问题的唯一方法,但我宁愿使用一些标准方法。有人有任何想法吗?

elasticsearch
1个回答
1
投票

我能想到的最好的就是使用inner_hits。例如:

PUT proptest
{
  "mappings": {
    "default": {
      "properties": {
        "product_id": {
          "type": "keyword"
        },
        "color": {
          "type": "keyword"
        },
        "props": {
          "type": "nested"
        }
      }
    }
  }
}

PUT proptest/default/1
{
  "product_id": "abc123",
  "color": "red",
  "props": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}
PUT proptest/default/2
{
  "product_id": "def",
  "color": "red",
  "props": [
  ]
}
PUT proptest/default/3
{
  "product_id": "ghi",
  "color": "blue",
  "props": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}

现在我们可以通过color查询并仅获取heightdepthfoobar属性:

GET proptest/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "color": {
              "value": "red"
            }
          }
        },
        {
          "bool": {
            "should": [
              {
                "nested": {
                  "path": "props",
                  "query": {
                    "match": {
                      "props.key": "height depth foobar"
                    }
                  },
                  "inner_hits": {}
                }
              },
              {
                "match_all": {}
              }
            ]
          }
        }

      ]
    }
  },
 "_source": {
   "excludes": "props"
 }
} 

输出是

{
  "hits": {
    "total": 2,
    "max_score": 2.2685113,
    "hits": [
      {
        "_index": "proptest",
        "_type": "default",
        "_id": "1",
        "_score": 2.2685113,
        "_source": {
          "color": "red",
          "product_id": "abc123"
        },
        "inner_hits": {
          "props": {
            "hits": {
              "total": 2,
              "max_score": 0.9808292,
              "hits": [
                {
                  "_index": "proptest",
                  "_type": "default",
                  "_id": "1",
                  "_nested": {
                    "field": "props",
                    "offset": 2
                  },
                  "_score": 0.9808292,
                  "_source": {
                    "key": "depth",
                    "value": 500
                  }
                },
                {
                  "_index": "proptest",
                  "_type": "default",
                  "_id": "1",
                  "_nested": {
                    "field": "props",
                    "offset": 1
                  },
                  "_score": 0.9808292,
                  "_source": {
                    "key": "height",
                    "value": 2000
                  }
                }
              ]
            }
          }
        }
      },
      {
        "_index": "proptest",
        "_type": "default",
        "_id": "2",
        "_score": 1.287682,
        "_source": {
          "color": "red",
          "product_id": "def"
        },
        "inner_hits": {
          "props": {
            "hits": {
              "total": 0,
              "max_score": null,
              "hits": []
            }
          }
        }
      }
    ]
  }
}

请注意,结果包含产品abc123def,并且已过滤了正确的属性。产品abc123与给定的属性列表部分匹配,def不包含任何属性列表。主要结果仅由外部查询color:red定义

该方法的缺点是在相同的顶级_source下,但在内部命中键下不会找到属性。

© www.soinside.com 2019 - 2024. All rights reserved.