【问题标题】:inner_hits does not work for nested filters when searching multiple indices搜索多个索引时,inner_hits 不适用于嵌套过滤器
【发布时间】:2023-03-24 14:55:04
【问题描述】:

Elasticsearch 版本 版本:6.2.2

我正在尝试搜索具有嵌套对象的多个索引。为了简单起见,我将使用这个例子。在查询中,我使用“inner_hits”属性。

PUT /sales
{
    "mappings": {
        "_doc" : {
            "properties" : {
                "tags" : { "type" : "keyword" },
                "comments" : { 
                    "type" : "nested",
                    "properties" : {
                        "username" : { "type" : "keyword" },
                        "comment" : { "type" : "text" }
                    }
                }
            }
        }
    }
}

PUT /sales/_doc/1?refresh
{
    "tags": ["car", "auto"],
    "comments": [
        {"username": "baddriver007", "comment": "This car could have better brakes"},
        {"username": "dr_who", "comment": "Where's the autopilot? Can't find it"},
        {"username": "ilovemotorbikes", "comment": "This car has two extra wheels"}
    ]
}

PUT /markets
{
    "mappings": {
        "_doc" : {
            "properties" : {
                "name" : { "type" : "keyword" },
                "products" : { 
                    "type" : "nested",
                    "properties" : {
                        "name" : { "type" : "keyword" },
                        "sku" : { "type" : "text" }
                    }
                }
            }
        }
    }
}

POST /sales,markets/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "should": [
              {
                "nested": {
                  "path": "comments",
                  "inner_hits": {

                  },
                  "ignore_unmapped": true,
                  "query": {
                    "match_all": {}
                  }
                }   
              }]
          }
        },
        {
          "bool": {
            "should": [
              {
                "nested": {
                  "path": "products",
                  "inner_hits": {

                  },
                  "ignore_unmapped": true,
                  "query": {
                    "match_all": {}
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

所以这个查询出错了

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_state_exception",
        "reason": "[match_all] no mapping found for type [comments]"
      },
      {
        "type": "illegal_state_exception",
        "reason": "[match_all] no mapping found for type [products]"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "markets",
        "node": "-22psoQNRLa8_Y9GeHBXaw",
        "reason": {
          "type": "illegal_state_exception",
          "reason": "[match_all] no mapping found for type [comments]"
        }
      },
      {
        "shard": 0,
        "index": "sales",
        "node": "-22psoQNRLa8_Y9GeHBXaw",
        "reason": {
          "type": "illegal_state_exception",
          "reason": "[match_all] no mapping found for type [products]"
        }
      }
    ]
  },
  "status": 500
}

但是当我在每个 "inner_hits": { "ignore_unmapped": true } 中添加 "ignore_unmapped": true 时,一切正常。这在 NEST .net 库中没有实现。

在“inner_hits”中使用“ignore_unmapped”是否正确,因为我没有在文档中找到它作为“inner_hits”属性? NEST 中是否有其他解决方案可以做到这一点。

更新

我尝试使用运算符重载查询,我得到了

Func<SearchDescriptor<object>, ISearchRequest> search = s => s.Type<object>()
                .Index(Indices.Index("sales", "markets"))
                .AllTypes()
                .Explain(false)
                .Query(q => (q
                    .Nested(n => n
                                .IgnoreUnmapped(true)
                                .Path(Infer.Field<SaleDocument>(f => f.Comments))
                                .InnerHits(ih => ih
                                    .Size(1)
                                )
                                .Query(q1 => q1
                                    .MatchAll()
                                )
                    ) && +q.Terms(t => t
                        .Field("_index")
                        .Terms(new[] { "sales" })
                    )
                ) || (q
                    .Nested(n => n
                        .IgnoreUnmapped(true)
                        .Path(Infer.Field<MarketDocument>(f => f.Products))
                        .InnerHits(ih => ih
                            .Size(1)
                        )
                        .Query(q1 => q1
                            .MatchAll()
                        )
                    ) && +q.Terms(t => t
                            .Field("_index")
                            .Terms(new[] { "markets" })
                        )
                )
            );

这段代码创建了查询

POST /sales,markets/_search
{
  "from": 0,
  "size": 10,
  "explain": false,
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "query": {
                    "match_all": {}
                  },
                  "path": "comments",
                  "inner_hits": {
                    "size": 1
                  },
                  "ignore_unmapped": true
                }
              }
            ],
            "filter": [
              {
                "terms": {
                  "_index": [
                    "sales"
                  ]
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "nested": {
                  "query": {
                    "match_all": {}
                  },
                  "path": "products",
                  "inner_hits": {
                    "size": 1
                  },
                  "ignore_unmapped": true
                }
              }
            ],
            "filter": [
              {
                "terms": {
                  "_index": [
                    "markets"
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

这又给出了错误

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_state_exception",
        "reason": "[match_all] no mapping found for type [comments]"
      },
      {
        "type": "illegal_state_exception",
        "reason": "[match_all] no mapping found for type [products]"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "markets",
        "node": "-22psoQNRLa8_Y9GeHBXaw",
        "reason": {
          "type": "illegal_state_exception",
          "reason": "[match_all] no mapping found for type [comments]"
        }
      },
      {
        "shard": 0,
        "index": "sales",
        "node": "-22psoQNRLa8_Y9GeHBXaw",
        "reason": {
          "type": "illegal_state_exception",
          "reason": "[match_all] no mapping found for type [products]"
        }
      }
    ]
  },
  "status": 500
}

【问题讨论】:

    标签: elasticsearch nest elasticsearch-net


    【解决方案1】:

    正如您所说,NEST 中似乎缺少 inner_hits 属性;我现在将打开一个问题以将其添加到下一个版本。

    ignore_unmapped 是在需要inner_hits 时处理此问题的方法。如果您不需要inner_hits,您可以将每个嵌套查询与"_index" 元数据字段上的term 查询结合起来,该字段在每种情况下都针对相应的索引名称,这样嵌套查询仅针对索引运行包含目标字段。

    【讨论】:

    • 我看到你已经加了github.com/elastic/elasticsearch-net/issues/3132,谢谢:)
    • 您好 Russ,感谢您的回复。我尝试在包含嵌套查询"should": [... { "nested": {..} }], "filter": { "term": { "_index": "sales" } } 的应该查询之后添加过滤器。我也在"nested": {..."query": {"bool": { "filter": { "term": {"_index": "sales" }}}}} 内部尝试过,但我得到了同样的错误。你能指出它应该在我的代码中的什么位置吗?
    • @GavrilOgnjanovski 您希望在类似于stackoverflow.com/a/45516969/1831_index 元数据字段上组合term 查询。本质上,&amp;&amp; 每个 term 查询每个嵌套查询,并以一元 + 为前缀,以确保它成为 bool 过滤子句。请参阅 elastic.co/guide/en/elasticsearch/client/net-api/current/… 了解查询中的运算符重载
    • 我用 NEST .net 代码和错误更新了我的答案。当我尝试获取 inner_hits 时仍然出现错误
    • NestedQueryBuilder.java。第 345 行的这段代码有问题吗? if (innerHitBuilder.isIgnoreUnmapped() == false) { throw new IllegalStateException("[" + query.getName() + "] no mapping found for type [" + path + "]");
    【解决方案2】:

    此问题已在这两个地方得到修复,并将在 NEST 或 ElasticSearch 的某些未来版本中提供。

    1. NEST .net 库通过在 InnerHits 中添加 IgnoreUnmapped() 方法。 https://github.com/elastic/elasticsearch-net/issues/3132

    2. 通过从嵌套查询 ignore_unmapped 属性继承 inner_hits 中的 ignore_unmapped 进行弹性搜索 https://github.com/elastic/elasticsearch/issues/29071

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-13
      • 2018-09-13
      相关资源
      最近更新 更多