Elasticsearch术语查询不会给出任何结果

时间:2015-10-10 11:16:43

标签: elasticsearch

我是Elasticsearch的新手,我必须执行以下查询:

GET book-lists/book-list/_search
{  
   "query":{  
      "filtered":{  
         "filter":{  
            "bool":{  
               "must":[  
                  {  
                     "term":{  
                        "title":"Sociology"
                     }
                  },
                  {  
                     "term":{  
                        "idOwner":"17xxxxxxxxxxxx45"
                     }
                  }
               ]
            }
         }
      }
   }
}

根据Elasticsearch API,它等同于伪SQL:

SELECT document
FROM   book-lists
WHERE  title = "Sociology"
       AND idOwner = 17xxxxxxxxxxxx45

问题是我的文档看起来像这样:

{  
   "_index":"book-lists",
   "_type":"book-list",
   "_id":"AVBRSvHIXb7carZwcePS",
   "_version":1,
   "_score":1,
   "_source":{  
      "title":"Sociology",
      "books":[  
         {  
            "title":"The Tipping Point: How Little Things Can Make a Big Difference",
            "isRead":true,
            "summary":"lorem ipsum",
            "rating":3.5
         }
      ],
      "numberViews":0,
      "idOwner":"17xxxxxxxxxxxx45"
   }
}

上面的Elasticsearch查询并没有返回任何内容。

然而,此查询返回上面的文档:

GET book-lists/book-list/_search
{  
   "query":{  
      "filtered":{  
         "filter":{  
            "bool":{  
               "must":[  
                  {  
                     "term":{  
                        "numberViews":"0"
                     }
                  },
                  {  
                     "term":{  
                        "idOwner":"17xxxxxxxxxxxx45"
                     }
                  }
               ]
            }
         }
      }
   }
}

这让我怀疑" title"两个字段的名称相同是为了什么。

有没有办法解决这个问题,而无需重命名任何字段。或者我在其他地方错过了它?

感谢任何想要帮助的人。

3 个答案:

答案 0 :(得分:11)

您的问题已在in the documentation中说明。

我怀疑您的索引没有任何显式映射,这意味着elasticsearch将使用动态映射。

对于字符串字段,它会将字符串传递给standard analyzer,这会降低字符串(除其他外)。这就是您的查询不起作用的原因。

您的选择是:

  1. 在字段上指定显式映射,以便在存储到索引(index: not_analyzed)之前不对其进行分析。
  2. 清理您的术语查询,然后将其发送到elasticsearch(在此特定查询中,lowercasing将起作用,但请注意标准分析器还会执行其他操作,例如删除停用词,因此根据标题您可能仍会遇到问题)。
  3. 使用其他查询类型(例如,query_string代替term,它将在运行之前分析查询。)
  4. 查看您存储的数据类型,您可能需要指定显式的not_analyzed映射。

    对于选项三,您的查询将如下所示:

    {  
       "query":{  
          "filtered":{  
             "filter":{  
                "bool":{  
                   "must":[  
                      {  
                         "query_string":{  
                            "fields": ["title"],
                            "analyzer": "standard",
                            "query": "Sociology"
                         }
                      },
                      {  
                         "term":{  
                            "idOwner":"17xxxxxxxxxxxx45"
                         }
                      }
                   ]
                }
             }
          }
       }
    }
    

    请注意,query_string查询具有特殊语法(例如,OR和AND不被视为文字),这意味着您必须小心提供它。因此,使用术语过滤器进行显式映射可能更适合您的用例。

答案 1 :(得分:1)

要扩展solarissmoke的解决方案,而该字段的内容将通过标准分析器,您的查询将不会。如果您在术语查询中引用Elasticsearch文档,您将看到未分析术语查询。

匹配查询可能更适合您的情况。默认情况下,您将以与标题字段内容相同的方式分析您查询的内容。 query_string查询为表格带来了更多内容,如果您打算使用它,则应查看文档。

所以再次使用小调整你的内容:

GET book-lists/book-list/_search
{  
   "query":{  
      "filtered":{  
         "filter":{  
            "bool":{  
               "must":[  
                  {  
                     "match":{  
                        "title":"Sociology"
                     }
                  },
                  {  
                     "term":{  
                        "idOwner":"17xxxxxxxxxxxx45"
                     }
                  }
               ]
            }
         }
      }
   }
}

重要的是要注意将术语小写版本传递给术语查询(hack - 看起来似乎不是一个好主意,因为solarissmoke描述了标准分析器的其他功能,如停止过滤器),使用query_string查询,或使用匹配查询仍然与您描述的SQL查询非常不同:

SELECT document
FROM   book-lists
WHERE  title = "Sociology"
       AND idOwner = 17xxxxxxxxxxxx45

使用这些Elasticsearch查询,您可以匹配idOwner可能相同的记录,但标题可能类似于“另一个社会学标题”,这与您对该SQL的期望不同。以下是文档中的一些很棒的内容和另一个stackoverflow文章,它将详细说明发生的事情,术语查询和过滤器是合适的,并获得完全匹配:

Elasticsearch : Finding Exact Values

Stackoverflow : Exact (not substring) matching in Elasticsearch

答案 2 :(得分:1)

我已在此blog中描述了此问题。 问题是由于Elasticsearch中的默认标记化。 同样,我概述了2个解决方案。 一种是在必填字段上启用not_analyzed标志,另一种是使用关键字tokenizer。