ElasticSearch:计算一组文档中一组单词出现的频率

时间:2015-04-24 08:13:29

标签: elasticsearch full-text-search data-mining word-frequency

我有以下ElasticSearch查询:

{
  "from": 0,
  "sort": [
    "_score"
  ],
  "fields": [
    "id",
    "title",
    "text"
  ],
  "query": {
    "query_string": {
      "fields": [
        "title",
        "text"
      ],
      "query": "(\"green socks\" OR \"red socks\") AND NOT (\"yellow\" OR \"blue\")"
    }
  },
  "size": 100
}

这很好用,并返回一组大约80,000个文档的文档。

我想在这组80,000份文件(即与"query": "(\"green socks\" OR \"red socks\") AND NOT (\"yellow\" OR \"blue\")")匹配的文件集上计算以下内容:

  • 每个"绿色袜子"计算一下。包含"绿袜子"的80,000个文件至少一次。
  • 每个"红袜子"计算一下。包含"红袜子"的80,000内的文件至少一次。
  • 依此类推,对于"左手"中的所有其他单词/短语上面查询字符串的一面。
  • 每个查询字符串中实际上大约有50-100个这样的单词/短语,所以另外还有50-100个这样的单词/短语"查询字符串中的单词/短语我实际上正在运行。

这感觉就像一个聚合查询,但我无法看到它 任何帮助v感激不尽,

谢谢,
R

2 个答案:

答案 0 :(得分:1)

你猜对了。这是聚合的工作。但如果您的映射不正确,聚合可能会很慢。例如,如果您对分析的字段(如“text”)进行聚合,这可能包含大量令牌,则会导致内存使用率过高,从而影响性能。

现在找到你的要求,你想要在80000结果的集合中包含说“红袜子”的文件的数量。您希望术语出现在任何位置(标题或文本字段中的表示)或仅存在于特定字段中。如果您希望它在任何字段中,那么您需要首先将字段组合在一个字段中。

您可以使用简单的terms aggregation以及您的查询,该查询将提供该字段中所有字词的计数。

{
  .................
  "query": {
    "query_string": {
      "fields": [
        "title",
        "text"
      ],
      "query": "(\"green socks\" OR \"red socks\") AND NOT (\"yellow\" OR \"blue\")"
    }
  },  
  "aggs" : {
    "my-terms" : {
        "terms" : {
            "field" : "title"
        }
    }
}

  "size": 100
}

如果您只想将某些术语计为“红袜子”“绿袜子”等,那么您应该使用filters aggregation

{
      .................
      "query": {
        "query_string": {
          "fields": [
            "title",
            "text"
          ],
          "query": "(\"green socks\" OR \"red socks\") AND NOT (\"yellow\" OR \"blue\")"
        }
      },  
      "aggs" : {
        "my-terms" : {
          "filters" : {
            "filters" : {
              "red socks" :   { "term" : { "title" : "red sock"   }},
              "green sock" : { "term" : { "title" : "green sock" }},
               ......
              and so on...
             }
         }
    }

      "size": 100
    }

请注意,正如我之前提到的,字段映射会影响聚合的性能和内存要求。

答案 1 :(得分:0)

除非你真的有exabytes数据,否则我建议使用Lucene而不是ElasticSearch来减少开销。当您可以更有效地直接访问JSON中的数据并通过网络发送数据时,没有用处...

除非您要加载80000个文档,否则我建议您再发送两个请求:

"green socks" AND NOT ("yellow" OR "blue")
"red socks" AND NOT ("yellow" OR "blue")

获取您感兴趣的计数。

可以一次完成所有这三项工作 - 如果您深入研究Lucene API,而不是通过文本搜索API。它是所有设置的交叉点,没什么了不起的。但同样,您不希望在不需要的情况下通过网络传输此类数据。