【问题标题】:Querying nested fields with analyzer results in error使用分析器查询嵌套字段会导致错误
【发布时间】:2018-04-15 05:20:03
【问题描述】:

我尝试为我已经工作的弹性搜索类型使用同义词分析器。这是我的 serviceEntity 的映射:

{
"serviceentity" : {
    "properties":{          
        "ServiceLangProps" : {
            "type" : "nested",
            "properties" : {
                "NAME"          : {"type" : "string", "search_analyzer": "synonym"},
                "LONG_TEXT"     : {"type" : "string", "search_analyzer": "synonym"},
                "DESCRIPTION"   : {"type" : "string", "search_analyzer": "synonym"},
                "MATERIAL"      : {"type" : "string", "search_analyzer": "synonym"},
                "LANGUAGE_ID"   : {"type" : "string", "include_in_all": false}
            }
        },
        "LinkProps" : {
            "type" : "nested",
            "properties" : {
                "TITLE" : {"type" : "string", "search_analyzer": "synonym"},
                "LINK"  : {"type" : "string"},
                "LANGUAGE_ID"   : {"type" : "string", "include_in_all": false}
            }
        },
        "MediaProps" : {
            "type" : "nested",
            "properties" : {
                "TITLE"     : {"type" : "string", "search_analyzer": "synonym"},
                "FILENAME"  : {"type" : "string"},
                "LANGUAGE_ID"   : {"type" : "string", "include_in_all": false}
            }
        }
    }
}

}

这些是我的设置

 {
  "analysis": {
    "filter": {
      "synonym": {
        "ignore_case": "true",
        "type": "synonym",
        "synonyms": [
          "lorep, spaceship",
          "ipsum, planet"
        ]
      }
    },
    "analyzer": {
      "synonym": {
        "filter": [
          "lowercase",
          "synonym"
        ],
        "tokenizer": "whitespace"
      }
    }
  }
}

当我试图搜索任何东西时,我得到这个错误:

Caused by: org.elasticsearch.index.query.QueryParsingException: [nested] nested object under path [ServiceLangProps] is not of nested type

我不明白为什么。如果我没有在我的设置中添加任何分析器,一切正常。

我正在使用 java API 与 elasticsearch 实例进行通信。因此,对于多匹配查询,我的代码看起来像这样:

MultiMatchQueryBuilder multiMatchBuilder = QueryBuilders.multiMatchQuery(fulltextSearchString, QUERY_FIELDS).analyzer("synonym");

java API 创建的查询字符串如下所示:

{
  "query" : {
    "bool" : {
      "must" : {
        "bool" : {
          "should" : [ {
            "nested" : {
              "query" : {
                "bool" : {
                  "must" : [ {
                    "match" : {
                      "ServiceLangProps.LANGUAGE_ID" : {
                        "query" : "DE",
                        "type" : "boolean"
                      }
                    }
                  }, {
                    "multi_match" : {
                      "query" : "lorem",
                      "fields" : [ "ServiceLangProps.NAME", "ServiceLangProps.DESCRIPTION", "ServiceLangProps.MATERIALKURZTEXT", "ServiceLangProps.DESCRIPTION_RICHTEXT" ],
                      "analyzer" : "synonym"
                    }
                  } ]
                }
              },
              "path" : "ServiceLangProps"
            }
          }, {
            "nested" : {
              "query" : {
                "bool" : {
                  "must" : [ {
                    "match" : {
                      "LinkProps.LANGUAGE_ID" : {
                        "query" : "DE",
                        "type" : "boolean"
                      }
                    }
                  }, {
                    "match" : {
                      "LinkProps.TITLE" : {
                        "query" : "lorem",
                        "type" : "boolean"
                      }
                    }
                  } ]
                }
              },
              "path" : "LinkProps"
            }
          }, {
            "nested" : {
              "query" : {
                "bool" : {
                  "must" : [ {
                    "match" : {
                      "MediaProps.LANGUAGE_ID" : {
                        "query" : "DE",
                        "type" : "boolean"
                      }
                    }
                  }, {
                    "match" : {
                      "MediaProps.TITLE" : {
                        "query" : "lorem",
                        "type" : "boolean"
                      }
                    }
                  } ]
                }
              },
              "path" : "MediaProps"
            }
          } ]
        }
      },
      "filter" : {
        "bool" : { }
      }
    }
  }
}

如果我在 LinkProps 或 MediaProps 上尝试它,我会得到相应嵌套对象的相同错误。

编辑:我使用的是 2.4.6 版的 elasticsearch

【问题讨论】:

    标签: elasticsearch nested


    【解决方案1】:

    也有助于检查查询字符串并了解正在使用的 ES 版本。

    我看不到 synonyms_path 以及您使用嵌套类型的事实可能会导致该错误。

    你可能已经看过了,但以防万一

    https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-synonym-tokenfilter.html

    【讨论】:

    • 感谢您的回复。我使用的是 2.4.6 版。我还将java api中的查询字符串添加到我的问题中。关于同义词路径:我不能将外部文件用于同义词。迟早所有同义词都来自数据库,我必须重新索引所有内容。但这不应该是我猜的重点。
    【解决方案2】:

    我创建了一个我正在尝试做的最小示例。

    我的映射如下所示:

    {
        "serviceentity" : {
            "properties":{          
                "LinkProps" : {
                    "type" : "nested",
                    "properties" : {
                        "TITLE" : {"type" : "string", "search_analyzer": "synonym"},
                        "LINK"  : {"type" : "string"},
                        "LANGUAGE_ID"   : {"type" : "string", "include_in_all": false}
                    }
                }
            }
        }
    }
    

    还有我在 JAVA 代码中对同义词分析器的设置:

    XContentBuilder builder = jsonBuilder()
            .startObject()
                .startObject("analysis")
                    .startObject("filter")
                        .startObject("synonym") // The name of the analyzer
                            .field("type", "synonym") // The type (derivate)
                            .field("ignore_case", "true") 
                            .array("synonyms", synonyms) // The synonym list
                        .endObject()
                    .endObject()
                    .startObject("analyzer")
                        .startObject("synonym")
                            .field("tokenizer", "whitespace")
                            .array("filter", "lowercase", "synonym")
                        .endObject()
                    .endObject()
                .endObject()
            .endObject();
    

    ElasticSearch Head Chrome 插件吐出的元数据如下所示:

    {
      "analysis": {
        "filter": {
          "synonym": {
            "ignore_case": "true",
            "type": "synonym",
            "synonyms": [
              "Test, foo",
              "Title, bar"
            ]
          }
        },
        "analyzer": {
          "synonym": {
            "filter": [
              "lowercase",
              "synonym"
            ],
            "tokenizer": "whitespace"
          }
        }
      }
    }
    

    当我现在使用搜索查询来查找“测试”时,我遇到了与我的第一篇文章中提到的相同的错误。这是查询

    {
      "query": {
        "bool": {
          "must": {
            "nested": {
              "path": "LinkProps",
              "query": {
                "multi_match": {
                  "query": "Test",
                  "fields": [
                    "LinkProps.TITLE",
                    "LinkProps.LINK"
                  ],
                  "analyzer": "synonym"
                }
              }
            }
          }
        }
      }
    }
    

    导致这个错误

    {
      "error": {
        "root_cause": [
          {
            "type": "query_parsing_exception",
            "reason": "[nested] nested object under path [LinkProps] is not of nested type",
            "index": "minimal",
            "line": 1,
            "col": 44
          }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
          {
            "shard": 0,
            "index": "minimal",
            "node": "6AhE4RCIQwywl49h0Q2-yw",
            "reason": {
              "type": "query_parsing_exception",
              "reason": "[nested] nested object under path [LinkProps] is not of nested type",
              "index": "minimal",
              "line": 1,
              "col": 44
            }
          }
        ]
      },
      "status": 400
    }
    

    当我用

    检查分析仪时
    GET http://localhost:9200/minimal/_analyze?text=foo&analyzer=synonym&pretty=true
    

    我答对了

    {
      "tokens": [
        {
          "token": "foo",
          "start_offset": 0,
          "end_offset": 3,
          "type": "word",
          "position": 0
        },
        {
          "token": "test",
          "start_offset": 0,
          "end_offset": 3,
          "type": "SYNONYM",
          "position": 0
        }
      ]
    }
    

    所以分析仪似乎设置正确。我搞砸了映射吗?我想问题不是因为我有嵌套对象,还是它?

    【讨论】:

      【解决方案3】:

      我刚试过这个

      {
        "query": {
          "bool": {
            "must": {
              "query": {
                "multi_match": {
                  "query": "foo",
                  "fields": [
                    "LinkProps.TITLE",
                    "LinkProps.LINK"
                  ],
                  "analyzer": "synonym"
                }
              }
            }
          }
        }
      }
      

      如您所见,我删除了“嵌套”包装器

      "nested": {
                "path": "LinkProps",
                ...
      }
      

      现在至少在某些结果中领先(还不确定,如果这些最终会是正确的结果)。我正在尝试将其应用于原始项目,如果这也有效,请随时通知您。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-04
        • 2021-09-29
        • 1970-01-01
        • 1970-01-01
        • 2019-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多