2013-03-08 61 views
20

Elasticsearch有两个类似的功能,以实现“类似”的文件:Elasticsearch“更多类似这样的” API与more_like_this查询

还有就是"More Like This API"。它给了我类似于给定的文件。尽管如此,我不能在更复杂的表达式中使用它。

还有"more_like_this" query for use in the Search API我可以在bool或boosting表达式中使用它,但是我不能给它一个文档的id。我必须提供"like_text"参数。

我有包含标签和内容的文档。有些文件会有很好的标签,有些则不会有。我想要一个每次都能工作的“类似文档”功能,但是会将具有匹配标签的文档进行排名高于具有匹配文本的文档。我的想法是:

{ 
    "boosting" : { 
     "positive" : { 
      "more_like_this" : { 
       "fields" : ["tag"], 
       "id" : "23452", 
       "min_term_freq" : 1 
      } 
     }, 
     "negative" : { 
      "more_like_this" : { 
       "fields" : ["tag"], 
       "id" : "23452", 
      } 
     }, 
     "negative_boost" : 0.2 
    } 
} 

显然,这并不工作,因为在"more_like_this"没有"id"。有什么选择?

回答

41

首先稍微介绍一下这个功能以及它是如何工作的。这个想法是,你有一个特定的文件,你想有一些其他类似的。

为了实现这一目标,我们需要从当前文档中提取一些内容并使用它来进行查询以获得相似的内容。我们可以从lucene存储的字段(或elasticsearch _source字段,它实际上是lucene中存储的字段)中提取内容,并以某种方式重新分析它,或者使用存储在术语向量中的信息(如果在索引时启用)来获取术语列表我们可以使用它来查询,而无需重新分析文本。我不确定elasticsearch是否尝试使用后一种方法,尽管可以使用术语向量。

more like this query允许您提供一个文本,无论您从哪里得到它。该文本将用于查询您选择的字段并找回相似的文档。文本不会被完全使用,但会被重新分析,并且在至少提供了min_term_freq(最小期限频率,默认值2)以及文档频率在min_doc_freqmin_doc_freq之间的文档中,仅保留最多max_query_terms(默认25) max_doc_freq。还有更多参数会影响生成的查询。

more like this api更进一步,允许提供一个文档的ID,并再次,一个字段列表。这些字段的内容将从该特定文档中提取,并用于在相同字段上更像此查询。这意味着生成的更像这个查询将具有包含以前提取的文本的属性文本,并将在相同的字段上执行。正如你所看到的,更像这个API执行一个更像这个查询之下的引擎。

让我们假设更像这个查询给你更多的灵活性,因为你可以将它与其他查询结合起来,并且你可以从你喜欢的任何来源获得文本。 另一方面,更像这个api公开的功能为你做了一些更多的工作,但有一些限制。

在你的情况下,我会结合几个不同的更像这样的查询在一起,以便您可以使用强大的弹性搜索查询DSL,不同地提升查询等。缺点是你必须自己提供文本,因为你不能提供文档的ID来提取它。

有不同的方法来实现你想要的。我将使用bool query将这两个更多的查询结合在一个should子句中,并赋予它们不同的权重。我也会使用more like this field query,因为您一次只想查询一个字段。

{ 
    "bool" : { 
     "must" : { 
      {"match_all" : { }} 
     }, 
     "should" : [ 
      { 
       "more_like_this_field" : { 
       "tags" : { 
        "like_text" : "here go the tags extracted from the current document!", 
        "boost" : 2.0 
       } 
       } 
      }, 
      { 
       "more_like_this_field" : { 
       "content" : { 
        "like_text" : "here goes the content extracted from the current document!" 
       } 
       } 
      } 
     ], 
     "minimum_number_should_match" : 1 
    } 
} 

这样至少应该有一个should子句匹配,标签上的匹配比内容匹配更重要。

+0

感谢您的回答。因此,唯一替代不存在的“id”JSON名称是获取全文并将其放置在“like_text”中。没有办法避免全文的往返。也没有办法减少它。例如。没有办法访问文档的vector这个术语,只能得到25个“顶级术语”,这样我就可以直接将它们放在''like_text''中,并获得与全文相同的结果。请确认。我正在考虑编写一个elasticsearch插件,它会给我一个文档的最佳条件。你认为这会起作用吗? – 2013-03-11 09:21:37

+0

据我所知,没有现成的方式来实现你想要的。你可以编写一个插件,公开一个类似于这个查询的新类型,它接受文档的id作为输入,并从中获取文本,甚至可以使用术语向量。 – javanna 2013-03-11 09:48:41

8

这是现在可能与新语法:

{ 
    "more_like_this" : { 
     "fields" : ["title", "description"], 
     "like" : [ 
     { 
      "_index" : "imdb", 
      "_type" : "movies", 
      "_id" : "1" 
     }, 
     { 
      "_index" : "imdb", 
      "_type" : "movies", 
      "_id" : "2" 
     }], 
     "min_term_freq" : 1, 
     "max_query_terms" : 12 
    } 
} 

在这里看到:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html

+1

在最近的ElasticSearch版本中,'docs'关键字已被弃用,而被赞成'like'。 – cosimo 2018-01-05 16:05:06

+0

@cosimo更新了答案,谢谢 – Datageek 2018-01-06 20:04:40