23

Elasticsearch 有两个相似的特性来获取“相似”的文档:

“更像这个 API”。它给了我类似于给定文件的文件。不过,我不能在更复杂的表达式中使用它。

还有"more_like_this"用于搜索 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
    }
}

显然这不起作用,因为没有"id"in "more_like_this"。有哪些替代方案?

4

2 回答 2

46

首先简单介绍一下这个功能及其工作原理。这个想法是您有一个特定的文档,并且您希望有一些与它相似的其他文档。

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

喜欢这个查询,您就可以提供文本,而不管您从哪里得到它。该文本将用于查询您选择的字段并返回类似的文档。文本不会被完全使用,但会重新分析,并且只会保留最多max_query_terms(默认 25 个),在至少具有提供的min_term_freq(最小词频,默认 2)和文档频率之间的词min_doc_freqmax_doc_freq。还有更多参数可以影响生成的查询。

更像这个 api更进一步,允许提供文档的 id 以及字段列表。这些字段的内容将从该特定文档中提取,并用于在相同字段上进行更像此查询。这意味着生成的更像这个查询将具有包含先前提取的文本的属性文本,并将在相同的字段上执行。正如你所看到的,这个 api 在后台执行的查询更像这个查询。

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

在你的情况下,我会将几个不同的更像这样的查询组合在一起,这样你就可以利用强大的弹性搜索查询 DSL,以不同的方式提升查询等等。缺点是您必须自己提供文本,因为您无法提供要从中提取文档的 id。

有不同的方法可以实现你想要的。我会使用bool 查询在 should 子句中将这两个查询组合起来,并赋予它们不同的权重。我也会改用更像这个字段的查询,因为您想一次查询一个字段。

{
    "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 子句必须匹配,并且标签上的匹配比内容上的匹配更重要。

于 2013-03-10T08:49:23.777 回答
11

现在可以使用新的like语法:

{
    "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

于 2015-07-20T19:41:47.117 回答