在搜索引擎中怎么实现完全匹配查询

 我来答
武汉肥猫科技
2017-01-18 · 武汉肥猫科技提供高端网站建设、SEO等服务
武汉肥猫科技
武汉肥猫网络科技有限公司,是一家集策划、设计、技术开发于一体的专业互联网产品服务公司,致力于为企业信息化提供驱动力。
向TA提问
展开全部

在有搜索引擎之前,我们查文档常使用顺序匹配。我们需要在文档中顺序扫描,找到完全匹配的子句。

有的情况精确匹配比搜索引擎的查找有优势,比如这样的内容”chinese:1388838245“,如果用户输入”883“希望搜到这则内容,在常规的情况下是搜不到的。

这是因为在有了搜索引擎后,我们对查询语句做的处理就不一样了。我们通常会先分词,然后查找对应的词条索引,最后得到评分由高到低的文档列表。上面的例句在常规的分词情况下,没有也不可能有”883“这个词条,因此搜索不到这则内容。

我一度以为没法实现完全匹配了,直到一个硬需求的出现。花了一天时间,把完全匹配用搜索引擎的思维整理出来。

简要描述实现思路,字段按一字一词的形式分词,再利用短语查询来搜索。

ES中,可以实现一字一词的的分词器是NGram。

它其实是一个上下文相连续字符的分词工具,可以看官方文档中的例子。当我们将它 min_gram 和 max_gram 都设为1时,它会按一字一词的形式分词。比如“shinyke@189.cn”,分词的结果是["s" , "h" , "i" , "n" , "y" , "k" , "e" , "@" , "1" , "8" , "9" , "." , "c" , "n" ]。

<pre name="code" class="javascript">/index_name/    
{  
  "settings": {  
    "analysis": {  
      "analyzer": {   
        "charSplit": {  
          "type": "custom",  
              "tokenizer": "ngram_tokenizer"  
        }  
      },  
     "tokenizer": {  
           "ngram_tokenizer": {  
             "type": "nGram",  
             "min_gram": "1",  
             "max_gram": "1",  
             "token_chars": [  
               "letter",  
               "digit",  
               "punctuation"  
             ]  
           }  
        }  
      }  
   }  
}

以上语句中,构建了一个名为“charSplit”的分析器。它使用一个名为“ngram_tokenizer”的Ngram分词器。

可以用如下语句测试charSplit分析器,可以看到一字一词的效果:

curl -POST http://IP:port/{index_name}/_analyze?pretty&analyzer=charSplit  
"测试语句"

把这个分析器在mapping里用起来:

...   
"sender": {  
   "type": "string",  
   "store": "yes",  
   "analyzer": "charSplit",  
   "fields": {  
     "raw": {  
       "type": "string",  
       "index": "not_analyzed"  
     }  
   },  
  ...

接下来就可以用match_phrase来实现完全匹配查询。

/{index_name}/{type_name}/_search  
{  
  "query": {  
    "multi_match": {  
      "query": "@189.cn",  
      "type": "phrase", //type指定为phrase  
      "slop": 0,        //slop指定每个相邻词之间允许相隔多远。此处设置为0,以实现完全匹配。  
      "fields": [  
        "sender"  
      ],  
      "analyzer": "charSplit", //分析器指定为charSplit  
      "max_expansions": 1        
    }  
  },  
  "highlight": {   //测试高亮是否正常  
    "pre_tags": [  
      "<b>"  
    ],  
    "post_tags": [  
      "</b>"  
    ],  
    "fragment_size": 100,  
    "number_of_fragments": 2,  
    "require_field_match": true,  
    "fields": {  
      "sender": {}  
    }  
  }  
}

phrase查询原始的作用是用来做短语查询,它有一个重要的特点:有顺序。我们利用了它匹配的有序性,限制slop为0,则可实现完全匹配查询。

以上语句返回的结果是:

{  
  
    "took": 18,  
    "timed_out": false,  
    "_shards": {  
        "total": 9,  
        "successful": 9,  
        "failed": 0  
    },  
    "hits": {  
        "total": 1,  
        "max_score": 0.40239456,  
        "hits": [  
            {  
                "_index": "index_name",  
                "_type": "type_name",  
                "_id": "AU9OLIGOZN4dLecgyoKp",  
                "_score": 0.40239456,  
                "_source": {  
                    "sender": "18977314000 <18977314000@189.cn>, 李X <18977314000@189.cn>, 秦X <18977314000@189.cn>, 刘X <18977314000@189.cn>"  
                },  
                "highlight": {  
                    "sender": [  
                        "18977314000 <18977314000<b>@</b><b>1</b><b>8</b><b>9</b><b>.</b><b>c</b><b>n</b>>, 李X <18977314000<b>@</b><b>1</b><b>8</b><b>9</b><b>.</b><b>c</b><b>n</b>>, 秦纯X <18977314000<b>@</b><b>1</b><b>8</b><b>9</b><b>.</b><b>c</b><b>n</b>>, 刘X <189773140"  
                    ]   
               }  
            }  
        ]  
    }  
  
}

到此,就实现了完全匹配查询。实际环境中用NGram做一字一词分析器的时候会更细致一些,比如有一些字符需要用stop word过滤掉。这些细节可以根据实际需要在构造分析器时添加filter实现,在此不做赘述。

柚鸥ASO
2024-03-16 广告
要用双引号,也就是“”。 搜索引擎其他扩展知识: 1、减号 “-”代表搜索不包含后面的页面,通常搜索一些词语同时又要排除某些词语出现的页面时,都会用到减号“-”的指令。在使用这个指令的时候减号的前面必须是空格,例如搜索seo-优化,这... 点击进入详情页
本回答由柚鸥ASO提供
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式