匹配有效时,简单字词查询无法与Elastic一起使用

时间:2018-09-19 18:44:12

标签: elasticsearch elastic-stack

我在Elastic中有一个如下所示的JSON对象。

{
    "_source" : {
      "version" : 1,
      "object_id" : "f1dcae27-7a6f-4fea-b540-901c09b60a15",
      "object_name" : "testFileName_for_TestSweepAndPrune",
      "object_type" : "",
      "object_status" : "OBJ_DELETED",
      "u_attributes" : ""
    }

}

我这样的词条查询不起作用。

{
            "query": {
                "term": {
                    "object_status": "OBJ_DELETED"
                }
            },
            "size": 10000

}

在相同条件下,匹配查询仍然可以正常工作。

{
            "query": {
                "match": {
                    "object_status": "OBJ_DELETED"
                }
            },
            "size": 10000

}

想知道这里会发生什么?如何在这种情况下使术语查询在这里起作用?

2 个答案:

答案 0 :(得分:5)

要了解为什么term查询无法按预期运行,我们需要检查ElasticSearch如何处理和保存数据以及matchterm查询有何不同。

通常,当您将某些文本保存到ElasticSearch中时,会先对其进行分析然后再保存。分析由analyzer完成。分析仪很多,但是如果您不指定任何分析仪,则将使用默认分析仪。分析器处理文本,将其转换为标记数组,并保存标记列表。对于每个特定的分析器,如何将文本拆分为令牌的规则是不同的。

在处理和保存文本后,您可以对其进行查询。查询内容的方法有很多,但在您的情况下,matchterm的主要区别在于matchfull text query,而term是{{3 }}。事实是,在全文搜索的情况下,您分析查询字符串的方式与分析查询字段的方式相同。在术语级别查询中,不分析查询字符串。请务必注意。

现在让我们看看"OBJ_DELETED"是如何分析ElasticSearch的。为此,我们可以添加简单的文档,如下所示:

curl -X PUT 'localhost:9200/testdata/object/1' -H 'Content-Type: application/json' -d '{ "object_status": "OBJ_DELETED"  }'

然后检查所有内容是否存在:

curl -X POST 'localhost:9200/testdata/_search?pretty'

应产生如下内容:

...
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
  {
    "_index" : "testdata",
    "_type" : "object",
    "_id" : "1",
    "_score" : 1.0,
    "_source" : {
      "object_status" : "OBJ_DELETED"
    }
  }
]

}

现在,我们可以检查"OBJ_DELETED"的分析方式:

curl -X POST 'localhost:9200/testdata/_analyze?pretty' -H 'Content-Type: application/json' -d '{ "text": "OBJ_DELETED"  }'

并输出:

{
  "tokens" : [
    {
      "token" : "obj_deleted",
      "start_offset" : 0,
      "end_offset" : 11,
      "type" : "<ALPHANUM>",
      "position" : 0
    }
  ]
}

如您所见,它仅将文本转换为小写并保存为一个标记。这就是默认分析器的工作方式。现在返回您的查询。 match查询之所以有效,是因为查询值"OBJ_DELETED"也被转换为小写形式,因此ElasticSearch可以找到它。对于term查询,查询字符串未处理,因此实际上您正在将OBJ_DELETEDobj_deleted进行比较,显然没有任何结果。

最后一个问题:为什么object_status.keyword用于term查询?

默认情况下,ElasticSearch为每个文本字段创建其他映射。您可以使用这种元数据。此外,它还允许您以不同的方式处理相同的值。因此,默认情况下,每个term level query字段都具有名称为keyword且类型为text的附加映射。 keyword个字段不进行分析(只有在需要时才可以对其进行规范化)。这意味着对于默认映射,它将保存您传递给ElasticSearch的确切值(在您的情况下为OBJ_DELETED)。

答案 1 :(得分:0)

您应该避免对term字段使用text查询(请参见term query notes in guidelines)。默认情况下,Elasticsearch在分析期间更改文本字段的值。例如,默认的standard analyzer会更改文本字段值,如下所示:

  • 删除大多数标点符号
  • 将其余内容分为单个单词,称为tokens
  • 小写令牌

您可以使用keyword analyzer从索引中的相应字段中生成正确且可搜索的term。 Elasticsearch提供了多种specify analyzers的方式。