【问题标题】:Elasticsearch -- count number of keyword occurences in a documentElasticsearch——统计文档中关键字出现的次数
【发布时间】:2019-07-15 09:09:18
【问题描述】:

数据库:Elasticsearch v7.2
应用:Laravel v5.7
使用 Elasticsearch/Elasticsearch (https://github.com/elastic/elasticsearch-php) 官方 PHP 库

我使用此代码对 Elasticsearch 进行 query_string 查询,以在我在整个索引中搜索时检索具有特定短语的文档

[
    "query_string" => [
        "default_field" => $content,
        "query" => $keywords
    ]
],

而$keywords 变量包含:

("MCU" OR "Marvel" OR "Spiderman")

现在,我想计算我要检索的文档中这些单词的 出现次数

我使用了 aggs 查询:

'aggs' => [
    'count' => [
        'terms' => [
            'field' => 'content.keyword'
        ]
    ]
]

但是,我不知道如何将这些doc_count 关联起来,并以匹配的方式显示它与命中 - 因为关键本身就是内容,而不是 ID

我计划显示整个文档,并确定每个文档中上述$keywords 出现的次数为Mentions

是否有其他方法可以在不使用 Elasticsearch 中的 aggs 的情况下计算出现次数?

【问题讨论】:

    标签: php elasticsearch


    【解决方案1】:

    如果您只想统计关键字的出现次数,则不必启用 fielddata,请尝试使用过滤器 aggs 以及您的查询

    GET my_index/_search
    {
      "query": {
        "query_string": {
          "default_field": "content", 
          "query": "MCU OR Marvel OR Spiderman"
        }
      },
      "aggs": {
        "count": {
          "filters": {
            "filters": {
              "mcu": {
                "match": {
                  "content": "MCU"
                }
              },
              "marvel": {
                "match": {
                  "content": "Marvel"
                }
              },
              "spiderman": {
                "match": {
                  "content": "Spiderman"
                }
              }
            }
          }
        }
      }
    }
    

    结果如下:

    {
      "took": 0,
      "timed_out": false,
      "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
      },
      "hits": {
        "total": 4,
        "max_score": 1.219939,
        "hits": [
          ....
          ....
        ]
      },
      "aggregations": {
        "count": {
          "buckets": {
            "marvel": {
              "doc_count": 2
            },
            "mcu": {
              "doc_count": 2
            },
            "spiderman": {
              "doc_count": 1
            }
          }
        }
      }
    }
    

    来源:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html

    【讨论】:

    • 您好先生,有没有办法在不使用aggs 的情况下计算我的$keywords 在文档(特别是CONTENT 字段)中出现的次数?
    • @JueViole17 更新了答案,添加了只计算关键字出现次数的新方法
    • 先生 @AshrafulIslam 感谢您对您的回复的有益更新,感谢!但是,我的 $keywords 变量是动态的——在我的 PHP 应用程序中,所有其他登录的用户都会更改 $keywords 的内容,因为 $keywords 是根据登录用户...我应该将您的答案更改为:"mcu": { "match": { "content": $keywords } }
    • @JueViole17 如果您将关键字放入匹配查询中,那么它将与总点击数相同。而是为每个关键字构建过滤器查询,格式为 "$keyword": { "match": { "content": $keyword } }
    • 您云使用 ElasticSearch Highlighting 功能突出显示您的搜索查询的出现,然后从 PHP 端开始计数。 elastic.co/guide/en/elasticsearch/reference/current/…
    【解决方案2】:

    感谢 @AshrafulIslam 先生,我能够提出 Elasticsearch 的功能 highlights。虽然highlights 字面上强调出现的关键字,但我使用了 PHP 的substr_count() 函数来计算<em> 标签

    我将此代码添加为['body']['query'] 元素的同级:

    "highlight" => [
        "fields" => [
            "content" => ["number_of_fragments" => 0]
        ],
        'require_field_match' => false
    ]
    

    然后当我循环遍历 ['hits']['hits'] 数组元素时,我执行了如下操作:

    $articles = $client->search($params);
    $hits = $articles['hits']['hits'];
    
    for($i=0; $i<count($hits); $i++){
        $hits[$i]['_source']['count_mentions'] = substr_count($hits[$i]['highlight']['content'][0],"<em>");
    }
    

    【讨论】:

      【解决方案3】:

      启用 Fielddata 可能不是启用文本搜索的最佳方式。

      https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html#before-enabling-fielddata

      在启用 fielddata 之前,请考虑为什么要使用文本字段进行聚合、排序或在脚本中。这样做通常没有意义。

      在索引之前分析文本字段,以便可以通过搜索 new 或 york 找到像 New York 这样的值。当您可能需要一个名为 New York 的存储桶时,此字段上的 terms 聚合将返回一个新存储桶和一个 york 存储桶。

      相反,您应该有一个用于全文搜索的文本字段,以及一个为聚合启用 doc_values 的未分析关键字字段,如下所示:

      PUT my_index
      {
        "mappings": {
          "properties": {
            "my_field": { 
              "type": "text",
              "fields": {
                "keyword": { 
                  "type": "keyword"
                }
              }
            }
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多