【问题标题】:ElasticSearch: Count Frequency of Occurrence of a Set of Words in a Set of DocumentsElasticSearch:计算一组文档中一组单词的出现频率
【发布时间】:2015-04-24 18:31:15
【问题描述】:

我有以下 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 个这样的“red socks”单词/短语。

这感觉像是一个聚合查询,但我就是看不到它。
非常感谢您的任何帮助,

谢谢,
回复

【问题讨论】:

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


    【解决方案1】:

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

    现在来满足您的要求,您希望在 80000 个结果集中包含“red sock”的文档计数。您希望该术语出现在任何地方(意味着在标题或文本字段中)或仅出现在特定字段中。如果您希望它出现在任何字段中,则需要先将这些字段合并到一个字段中。

    您可以在查询中使用简单的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
    }
    

    如果您只想将某些术语计算为“red socks”“green sock”等,那么您应该使用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
        }
    

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

    【讨论】:

    • 非常感谢。最后,“过滤器聚合”是需要的。因为这是一个报告工具,而不是一个关键的前端服务,“过滤器聚合”目前看来是合适的。
    【解决方案2】:

    除非您确实拥有 EB 级数据,否则我建议您使用 Lucene 而不是 ElasticSearch 来减少开销。当您可以更有效地直接访问它时,将 JSON 中的数据序列化并通过网络发送它是没有用的......

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

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

    获取您感兴趣的计数。

    如果您深入研究 Lucene API,而不是通过文本搜索 API,可以同时完成这三个操作。都是固定的十字路口,没什么了不起的。但同样,您不想在没有必要的情况下通过网络传输此类数据。

    【讨论】:

    • 我不同意你的第一条评论。 ElasticSearch 或 Solr 不是关于数据的大小,而是关于在 Lucene 之上提供一个抽象层。你所说的类似于“当你可以直接在汇编中编写代码以获得更好的性能时,用 C 语言编写是没有意义的”
    • 你可以在底层使用 Lucene,但它已经带有很多“抽象”(这些层实际上并没有抽象任何东西,就像 C 不是汇编的抽象一样)。如果您实际上可以交换底层引擎,那么抽象将是,但 Solr 和 ElasticSearch 不能使用例如据我所知,Xapian 而不是 Lucene。它们主要是 Lucene 的 Web 服务器 API;并且它们使许多在 Lucene 中非常容易做的事情非常变得复杂。
    猜你喜欢
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多