首页 > 解决方案 > 要求 Elasticsearch 高亮用双引号 (") 括起来的单词,而不是截断它们

问题描述

Elasticsearch:v7.2
应用程序:PHP - Laravel v5.7

你好,美好的一天!

我正在开发一个类似于搜索引擎的 Web 应用程序,而用户将输入将指定给变量的单词$keywords。然后我有这个查询来搜索我的索引:

$params = [
    'index' => 'my_index',
    'type'  => 'my_type',
    'from'  => 0,
    'size'  => 10,
    'body'  => [
        "query" => [
            'bool' => [
                'must' => [
                    [
                        "query_string" => [
                            "fields" => ['title','content'],
                            "query" => $keywords
                        ]
                    ]
                ]
            ]
        ]
    ]
];

$articles = $client->search($params);

现在,根据我之前的帖子,我能够计算我$keywords在索引文档中出现的次数。

这是我highlight附加到$params上述内容的查询:

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

$keywords使用双引号 (") 括起来,highlighter仍然会截断/分隔$keywords并且我已经用双引号指定它​​们以严格遵循这些words

例如,我的 $keywords contains "Ayala Alabang",但是当我显示输出时,它是这样的

样本输出

它们是分开的$keywords,但根据输出,它们只是彼此相邻。

我的查询是否有任何其他调整或修订?我在一些论坛上发现了一些相关的帖子或问题,他们最后的回复是从 2019 年 3 月开始的,任何建议都会对这个困境有很好的帮助

标签: elasticsearch

解决方案


在深入研究文档几天后,我找到了一种方法来正确隔离文档中的关键字

第1步

应用"explain" => true在你的$params

$params = [
            'index' = "myIndex",
            'type'  => "myType",
            'size'  => 50,
            'explain' => true,
            'query' => [
                'match_all' => [
                    //your elasticearch query here
                ]
            ]
]

第2步

$client->search($params)然后在执行代码后获取结果:

$result = $client->search($params);

然后一个长的文字解释将包含在你的$result,而你的keywords和他们的frequency将以文本格式显示。:

try displaying via dd($result['explanation'])

注意这里的问题是很多嵌套数组都会是_explanation数组键的内容,所以我们想出了一个递归函数来查找keywords和他们的frequency

第 3 步

您需要创建一个函数,该函数将在重复字符串或其他字符串之间获取字符串

public static function get_string_between($string, $start, $end){
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}

第4步

然后创建递归函数:

public static function extract_kwds($expln,$kwds)
{
    foreach($expln as $k=>$v)
    {
        if($k == 'description' && strpos(json_encode($v),'weight(')!==false)
        {
            if(isset($kwds[$this->get_string_between($v,':',')')]))
            {
                $kwds[$this->get_string_between($v,':',')')] += intVal($this->get_string_between($expln['details'][0]['description'],'score(freq=',')'));
            }
            else
            {
                $kwds[$this->get_string_between($v,':',')')] = intVal($this->get_string_between($expln['details'][0]['description'],'score(freq=',')'));
            }
        }
        if($k == 'details' && count($v) != 0)
        {
            foreach($v as $k2=>$v2)
            {
                $kwds = $this->extract_kwds($v2,$kwds);
            }
        }
    }
    return $kwds;
}

最后

我能够获取所有这些内容keywords以及它们在文档中出现的frequency次数。keywords


推荐阅读