简体   繁体   English

使用嵌套字段嵌套值过滤文档 Elastic Search

[英]Filtering Documents with nested field nested value Elastic Search

My Data demo:我的数据演示:

{
  "id": "1",
  "username": "demo",
  "email": "dasdasdas@dsadas",
  "number": "000111000",
  "createdDate": "2022-07-13",
  "educations": [
    {
      "name": "test01",
      "score": "5.00",
      "config": {
        "configName": "Ha Ha",
        "isVisible": true
      }
    },
    {
      "name": "demo02",
      "score": "4.50",
      "config": {
        "configName": "Hi Hi",
        "isVisible": false
      }
    },
    {
      "name": "demo03",
      "score": "4.00",
      "config": {
        "configName": "Hu Hu",
        "isVisible": true
      }
    }
  ]
}

Now, I want to show all data where educatations.config.isVisible = true现在,我想显示educatations.config.isVisible = true的所有数据

my java code that I tried is following:我尝试的java代码如下:

boolQueryBuilder = boolQueryBuilder.must(
                       nestedQuery("educations.config", 
                           termQuery("educations.config.isVisible", true),
                           ScoreMode.Total));

But It's returning all data.但它正在返回所有数据。

Can anyone help me out with the query.谁能帮我查询一下。

Well, the demo data you provided consists of one single document, which inside of a nested array has the data you want to filter on.好吧,您提供的演示数据由一个文档组成,嵌套数组中包含您要过滤的数据。

By default, Elasticsearch will always return all complete documents that match a query.默认情况下,Elasticsearch 将始终返回与查询匹配的所有完整文档。 Since one of the nested fields matches your query, the complete source is returned.由于其中一个嵌套字段与您的查询匹配,因此将返回完整的源。 This is correct and intended behavior.这是正确和预期的行为。

If you instead want partial hits of one document, there are several options, though none of them may yield exactly what you intend:如果您想要一个文档的部分命中,有几个选项,尽管它们都不能产生您想要的结果:

While you could use _source_includes and/or _source_excludes to get partial results from Elasticsearch, afaik you cannot do so conditionally.虽然您可以使用_source_includes和/或_source_excludes从 Elasticsearch 获取部分结果,但您不能有条件地这样做。 Ie you could即你可以

GET test_index/_search?_source_excludes=educations

but this will remove all educations fields from the result, not based on a condition like your question entails.但这将从结果中删除所有educations领域,而不是基于您的问题所涉及的条件。

A way to kind of get what you want is to use inner_hits in a nested query :一种获得所需内容的方法是在嵌套查询中使用inner_hits

GET test_index/_search
{
  "query": {
    "nested": {
      "path": "educations.config",
      "query": {
        "match": {"educations.config.isVisible": true}
      },
      "inner_hits": {} 
    }
  }
}

Each hit will have an additional section inner_hits that contains only the (sub-)hits for the nested fields that meet the search condition.每个hit都会有一个额外的部分inner_hits ,其中仅包含满足搜索条件的嵌套字段的(子)命中。 By default the _source of the returned hits inside inner_hits is relative to the _nested metadata.默认情况下, inner_hits中返回的命中的_source是相对于_nested元数据的。 So in the above example only the config part is returned per nested hit and not the entire source of the top level document:所以在上面的例子中,每个嵌套命中只返回config部分,而不是顶层文档的整个源:

"_source" : {
  "id" : "1",
  "username" : "demo",
  "email" : "dasdasdas@dsadas",
  "number" : "000111000",
  "createdDate" : "2022-07-13",
  "educations" : [
    {
      "name" : "test01",
      "score" : "5.00",
      "config" : {
        "configName" : "Ha Ha",
        "isVisible" : true
      }
    },
    {
      "name" : "demo02",
      "score" : "4.50",
      "config" : {
        "configName" : "Hi Hi",
        "isVisible" : false
      }
    },
    {
      "name" : "demo03",
      "score" : "4.00",
      "config" : {
        "configName" : "Hu Hu",
        "isVisible" : true
      }
    }
  ]
},
"inner_hits" : {
  "educations.config" : {
    "hits" : {
      "total" : {
        "value" : 2,
        "relation" : "eq"
      },
      "max_score" : 0.4700036,
      "hits" : [
        {
          "_index" : "test_index",
          "_type" : "_doc",
          "_id" : "dQSz94EBbpRrdmjWWpzK",
          "_nested" : {
            "field" : "educations.config",
            "offset" : 0
          },
          "_score" : 0.4700036,
          "_source" : {
            "configName" : "Ha Ha",
            "isVisible" : true
          }
        },
        {
          "_index" : "test_index",
          "_type" : "_doc",
          "_id" : "dQSz94EBbpRrdmjWWpzK",
          "_nested" : {
            "field" : "educations.config",
            "offset" : 2
          },
          "_score" : 0.4700036,
          "_source" : {
            "configName" : "Hu Hu",
            "isVisible" : true
          }
        }
      ]
    }
  }
}

For a java solution, check the NestedQueryBuilder returned by QueryBuilders.nestedQuery in order to configure inner_hits there.对于 java 解决方案,请检查NestedQueryBuilder返回的QueryBuilders.nestedQuery以便在那里配置inner_hits The following SO post on Elasticsearch inner hits in java api may also help.以下关于Java api 中 Elasticsearch 内部命中的SO 帖子也可能有所帮助。

You could also combine the two ( _source_exclude and inner_hits ) to make your response more compact, assuming education is also of nested type:您还可以将两者( _source_excludeinner_hits )结合起来,以使您的响应更加紧凑,假设education也是nested类型:

GET test_index/_search?_source_excludes=educations
{
  "query": {
    "nested": {
      "path": "educations",
      "query": {
        "match": {"educations.config.isVisible": true}
      },
      "inner_hits": {} 
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM