在弹性搜索

时间:2015-10-23 14:08:25

标签: elasticsearch

给出这样的短语匹配查询:

{
    'match_phrase': {
        'text.english': {
            'query': "The fox jumped over the wall",
            'phrase_slop': 4,
        }
    }
}

有没有办法可以按照完全匹配对结果进行分组?

因此,如果我有1个文件text.english包含“快速狐狸跳过小墙”和3个包含“懒狐狸跳过大墙”的文件,我最终得到了这两组结果

我可以运行多个查询并在ES之外进行一些处理,但我需要一个能够在大量文档上合理执行的解决方案。理想情况下,我希望有一种方法可以使用我错过的聚合来做到这一点。

我提出的最佳解决方案是使用突出显示运行上面的查询,解析所有结果中的所有突出显示,并根据突出显示内容对它们进行分组。这适用于非常小的结果集,但是在超过1000个文档结果集中,它非常慢。

修改 也许我可以让这一点更清楚。如果我有包含以下值的示例文档:

  1. “快速的狐狸跳过小墙.Blah blah blah很多页不相关的文字。”
  2. “懒惰的狐狸跳过了大墙.Blah blah blah with many pages of different related text。”
  3. “懒惰的狐狸跳过了大墙.Blah blah blah with many pages of different related text。”
  4. “懒惰的狐狸跳过了大墙.Blah blah blah with many pages of different related text。”
  5. 我希望能够将我的结果分组如下,查询文字“狐狸跳过墙”:

    • “快速狐狸跳过小墙” - 文件1
    • “懒狐狸跳过大墙” - 文件2,3,4

4 个答案:

答案 0 :(得分:2)

如果text.english中的陈述“完全”相同,那么他们的分数应该相同。您可以根据Elastic Search _score汇总结果。

请参阅此问题ElasticSearch: aggregation on _score field?

由于ES已禁用动态脚本,因此这可能会有所帮助。 ElasticSearch: aggregation on _score field w/ Groovy disabled

答案 1 :(得分:2)

在我看来,highlighting是唯一的选择,因为它是Elasticsearch显示文本的哪些“部分”匹配的唯一方式。在您的情况下,您希望根据“匹配的内容”对文档进行分组。

如果文本会更短(就像几个单词),也许更复杂的解决方案就是以shingle方式分割文本 - 以某种方式对这些短语进行分组... 也许

但是对于文本页面,我认为唯一的选择是使用突出显示并在之后执行其他步骤来对突出显示的部分进行分组。

答案 2 :(得分:0)

我在产品搜索应用程序中遇到类似的问题/挑战。我想按品牌分组产品,例如

Nikon
Nikos

为了解决这个问题,我试验了Suggester 。背后的想法是建议者将为我提供搜索建议。这些建议将被分组,不会对所有文档重复(即使它们周围可能还有其他文本)。您可以使用Term SuggesterPhrase Suggester

但是,这种方法可能需要您更改结果的处理方式。您必须将建议显示为组并分别处理搜索结果。这种方法的优点是您不必自己进行分组。

另一个解决方案是使用带状疱疹的Terms Aggregation。此聚合将对单词组(带状疱疹)进行分组。但是,要获得结果,您必须获取所有聚合并将其与查询输入相匹配。请参阅示例映射,数据和查询:

PUT /so
{
   "settings": {
      "analysis": {
         "analyzer": {
            "suggestion_analyzer": {
               "tokenizer": "standard",
               "filter": [
                  "lowercase"
               ]
            },
            "analyzer_shingle": {
               "type": "custom",
               "tokenizer": "standard",
               "filter": [
                  "filter_shingle"
               ]
            }
         },
         "filter": {
            "filter_shingle": {
               "type": "shingle",
               "min_shingle_size": 4,
               "max_shingle_size": 16,
               "output_unigrams": "false"
            }
         }
      }
   },
   "mappings": {
      "d": {
         "properties": {
            "text": {
               "properties": {
                  "english": {
                     "type": "string",
                     "fields": {
                        "shingles": {
                           "type": "string",
                           "analyzer": "analyzer_shingle"
                        },
                        "suggest": {
                           "type": "completion",
                           "index_analyzer": "analyzer_shingle",
                           "search_analyzer": "analyzer_shingle",
                           "payloads": true
                        }
                     }
                  }
               }
            }
         }
      }
   }
}

文件1:

POST /so/d/1
{
    "text": {
        "english": "The quick fox jumps over the big wall. JJKJKJKJ"
    }
}

文件2:

POST /so/d/2
{
    "text": {
        "english": "The quick fox jumps over the small wall. JJKJKJKJ"
    }
}

文件3:

POST /so/d/3
{
    "text": {
        "english": "The quick fox jumps over the gugus wall. LLLLLLL"
    }
}

查询:

POST /so/_search
{
    "size": 0,
    "query": {
        "match": {
           "text.english": "The quick fox jumps over the wall"
        }
    }, 
    "aggs" : {
        "states" : {
            "terms" : {
                "field" : "text.english.shingles",
                "size": 40
            }
        }
    }
}

答案 3 :(得分:-1)

我相信您可以在未分析的字段版本上创建字词聚合。

如果text.raw定义为not_analyzed,则聚合应采用整个字段值。

我没有测试过,但我发现了类似的东西:ElasticSearch terms aggregation by entire field