【问题标题】:elasticsearch php not return search result without spaceelasticsearch php不返​​回没有空格的搜索结果
【发布时间】:2020-09-12 10:47:23
【问题描述】:

我在 elasticsearch 索引 products_idx1 中添加了 15k 条记录并输入 product

在像apple iphone 6 这样的记录产品名称中,所以当我搜索iphone6 时它返回空数据。

这是我在 php elasticsearch 中的代码

<?php

    use Elasticsearch\ClientBuilder;

    require 'vendor/autoload.php';

   $client = ClientBuilder::create()->build();
 $values =['name','name.prefix','name.suffix','sku'];
$params =
[
'client'=>['verify'=>1,'connect_timeout'=>5],
'from'=> 0,
'size'=>25,
 'body'  =>[
'query' => [
 'bool'=>
            [
            'should'=> [[
                'multi_match'=> ['query'=>'iphone6','type'=>'cross_fields','fields'=>$values,'operator'=>'OR']
                ],
                ['match'=>['all'=>['query'=>'iphone6','operator'=>'OR','fuzziness'=>'AUTO'] ]]
                ]
            ]

],
'sort'=>['_score'=>['order'=>'desc']],
],

'index'=>'products_idx1'
];

 $response = $client->search($params);
echo "<pre>";print_r($response);

【问题讨论】:

  • 你只得到“iphone”的结果吗?
  • 不,我只是举个例子,如果有人像 appleiphone 搜索,那么它应该返回结果,所以我应该做搜索分析器吗?
  • @Nate 现在,如果我搜索“iphone6”,我得到的结果为零
  • 您需要有匹配的标记,并且 b/c ES 默认将文本拆分为空格上的标记我认为这就是为什么您使用这些查询获得 0 个结果的原因。有prefix 查询可能会有所帮助,您可以设置另一个字段变体,其中所有空格都被删除作为备用分析。有很多选择
  • @Nate 我不知道正确的方法。如果您向我提供参考链接,我可以对此进行研究并在我的项目中实施

标签: php elasticsearch elasticsearch-analyzers


【解决方案1】:

使用 shinglepattern_replace token filter 可以获得所有 3 个搜索词的结果,这些搜索词在问题和评论中提到,又名 iphoneiphone6appleiphone,下面是它的完整示例。

正如评论中所解释的,您搜索从搜索词生成的时间标记应该与从索引文档生成的索引时间标记匹配,以便获得搜索结果,这就是我通过创建自定义实现的分析仪。

索引映射

{
  "settings": {
    "analysis": {
      "analyzer": {
        "text_analyzer": {
          "tokenizer": "standard",
          "filter": [
            "shingle",
            "lowercase",
            "space_filter"
          ]
        }
      },
      "filter": {
        "space_filter": {
          "type": "pattern_replace",
          "pattern": " ",
          "replacement": "",
          "preserve_original": true
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "text_analyzer"
      }
    }
  }
}

为您的示例文档编制索引

{
  "title" : "apple iphone 6" 
}

appleiphone 的搜索查询和结果

{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "appleiphone"
          }
        }
      ]
    }
  }
}

结果

"hits": [
      {
        "_index": "ana",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.3439677,
        "_source": {
          "title": "apple iphone 6",
          "title_normal": "apple iphone 6"
        }
      }
    ]

搜索查询iphone6 并获得结果

{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "iphone6"
          }
        }
      ]
    }
  }
}

结果

 "hits": [
      {
        "_index": "ana",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.3439677,
        "_source": {
          "title": "apple iphone 6",
          "title_normal": "apple iphone 6"
        }
      }
    ]

最后但并非最不重要的搜索查询iphone

{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "iphone"
          }
        }
      ]
    }
  }
}

结果

"hits": [
      {
        "_index": "ana",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.3439677,
        "_source": {
          "title": "apple iphone 6",
          "title_normal": "apple iphone 6"
        }
      }
    ]

【讨论】:

  • 感谢您的努力,但当我搜索“iphone6”时,它仍然返回零数据,但如果我添加新文档“apple iphone x”,然后按“iphonex”搜索,它会返回“apple iphone x”,为什么不搜索iphone6?
  • @NirajPatel 因为您正在更改控制数据如何被标记化和索引的分析器,如其他用户所提到的,并且在我的回答中以粗体显示,您需要再次创建重新索引数据,这似乎适合您的@ 987654337@ 例如,您没有重新索引数据。 最好是在本地使用我的映射创建一个新索引并对其进行测试以更好地理解另外请不要忘记投票并接受答案:)
  • 但是我创建了一个新索引并在其中注入了新文档
  • @NirajPatel 这很奇怪,您可以在我的回答中看到它有效,我已在本地亲自尝试过,希望您在搜索 iphone6 之前已将 apple iphone 6 编入索引?
  • 我接受了你的回答并给了 50 分并投票,但我仍然无法搜索 iphone6
【解决方案2】:

由于我的答案已经很大,出于可读性原因以及对 Elasticsearch 和 how it works 中的分析器不太熟悉的人们,将有关 analyze API 的信息添加到另一个答案中。

在我之前的回答中,@Niraj 提到其他文档正在工作,但他遇到了iphone6 查询的问题,因此为了调试问题,anlyze API 非常有用。 p>

首先检查您认为应该与您的搜索查询匹配的文档的索引时间标记,在这种情况下,apple iphone 6

PUT http://{{hostname}}:{{port}}/{{index}}/_analyze

{
"text" : "apple iphone 6",
"analyzer" : "text_analyzer"
}

并生成令牌

{
"tokens": [
{
"token": "apple",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "appleiphone",
"start_offset": 0,
"end_offset": 12,
"type": "shingle",
"position": 0,
"positionLength": 2
},
{
"token": "iphone",
"start_offset": 6,
"end_offset": 12,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "iphone6", //note this carefully
"start_offset": 6,
"end_offset": 14,
"type": "shingle",
"position": 1,
"positionLength": 2
},
{
"token": "6",
"start_offset": 13,
"end_offset": 14,
"type": "<NUM>",
"position": 2
}
]
}

现在您可以看到我们使用的分析器创建 iphone6 也作为令牌,现在检查搜索时间令牌

{
  "text" : "iphone6",
  "analyzer" : "text_analyzer"
}

和令牌

{
    "tokens": [
        {
            "token": "iphone6",
            "start_offset": 0,
            "end_offset": 7,
            "type": "<ALPHANUM>",
            "position": 0
        }
    ]
}

现在您可以注意到搜索标记也将 iphone6 创建为索引时间标记中存在的标记,这就是它会匹配我在完整示例中给出的搜索查询的原因第一个答案

【讨论】:

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