【问题标题】:Elasticsearch - Count of matches per documentElasticsearch - 每个文档的匹配数
【发布时间】:2019-05-03 23:44:05
【问题描述】:

我正在使用此查询来搜索字段中出现的短语。

"query": {
    "match_phrase": {
       "content": "my test phrase"
  }
 }

我需要计算每个文档中每个短语的匹配次数(如果可能的话?)

我考虑过聚合器,但认为这些不符合要求,因为它们会给我提供整个索引而不是每个文档的匹配数。

谢谢。

【问题讨论】:

  • 我想不出比你在discuss.elastic.co/t/count-of-phrase-matches-per-document/96762 得到的答案更好的了。如果您有更好的解决方案,请在此处发布:我正在寻找相同的东西。
  • 您也许可以使用突出显示,将“number_of_fragments”设置为一个高数字并计算返回的片段数? elastic.co/guide/en/elasticsearch/reference/current/…
  • 这个问题有点模棱两可,因为 Elasticsearch 会将单个单词匹配计为命中,例如“短语”将匹配“我的测试短语”,因此当短语在同一文档中全部和部分匹配时,“每个文档的每个短语发生了多少匹配”的答案并不完全清楚。

标签: elasticsearch


【解决方案1】:

这可以通过使用Script Fields /painless 脚本来实现

您可以计算每个字段的出现次数并将其添加到文档中。

例子:

## Here's my test index with some sample values

POST t1/doc/1  <-- this has one occurence
{
  "content" : "my test phrase"
}

POST t1/doc/2    <-- this document has 5 occurences
{
   "content": "my test phrase ",
   "content1" : "this is my test phrase 1",
   "content2" : "this is my test phrase 2",
   "content3" : "this is my test phrase 3",
   "content4" : "this is my test phrase 4"

}

POST t1/doc/3
{
  "content" : "my test new phrase"
}

现在使用脚本我可以计算每个字段的短语匹配。我每个字段计算一次,但您可以修改脚本以每个字段进行多重匹配。

显然,这里的缺点是您需要在脚本中提及文档中的每个字段,除非有一种方法可以循环遍历我不知道的 doc 字段。

POST t1/_search
{
  "script_fields": {
    "phrase_Count": {
      "script": {
        "lang": "painless",
        "source": """
                             int count = 0;

                            if(doc['content.keyword'].size() > 0 && doc['content.keyword'].value.indexOf(params.phrase)!=-1) count++;
                            if(doc['content1.keyword'].size() > 0 && doc['content1.keyword'].value.indexOf(params.phrase)!=-1) count++;
                            if(doc['content2.keyword'].size() > 0 && doc['content2.keyword'].value.indexOf(params.phrase)!=-1) count++;
                            if(doc['content3.keyword'].size() > 0 && doc['content3.keyword'].value.indexOf(params.phrase)!=-1) count++;
                            if(doc['content4.keyword'].size() > 0 && doc['content4.keyword'].value.indexOf(params.phrase)!=-1) count++;

                            return count;
""",
        "params": {
          "phrase": "my test phrase"
        }
      }
    }
  }
}

这会给我每个文档的短语计数作为脚本字段

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "t1",
        "_type" : "doc",
        "_id" : "2",
        "_score" : 1.0,
        "fields" : {
          "phrase_Count" : [
            5                 <--- count of occurrences of the phrase in the document
          ]
        }
      },
      {
        "_index" : "t1",
        "_type" : "doc",
        "_id" : "1",
        "_score" : 1.0,
        "fields" : {
          "phrase_Count" : [
            1
          ]
        }
      },
      {
        "_index" : "t1",
        "_type" : "doc",
        "_id" : "3",
        "_score" : 1.0,
        "fields" : {
          "phrase_Count" : [
            0
          ]
        }
      }
    ]
  }
}

【讨论】:

  • 查询匹配不是简单的子字符串怎么样。假设我的搜索是像 "my phrase"~3 这样的邻近搜索,我想计算匹配数?
  • @Rich 这需要一些代码更改。 Painless 是建立在 Java 之上的,我相信你可以rewrite the script to achieve proximity search
  • 感谢您的回复,但这不是我正在寻找的解决方案。我不想尝试在“无痛”脚本语言中重现所有 Elasticsearch / Lucene 查询语法解析代码。我正在寻找一个使用 Elasticsearch 代码的答案,例如 discuss.elastic.co/t/count-of-phrase-matches-per-document/96762 的答案开头的 explain
【解决方案2】:

您可以使用术语向量来实现此功能。请看一看 Term Vectors

【讨论】:

  • 请提供一个他们将如何使用它们的示例,而不仅仅是一个链接。
  • 我认为这行不通:我正在执行“match”查询,而不是“term”查询,我不想从我的文档(可能很大),但只是对我的搜索短语的匹配数的计数。不过我可能误解了你,你能举个例子吗?
猜你喜欢
  • 2013-03-10
  • 2019-11-30
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
相关资源
最近更新 更多