资讯专栏INFORMATION COLUMN

ElasticSearch结构化搜索和全文搜索

googollee / 642人阅读

摘要:结构化搜索精确值查找过滤器很重要,因为它们执行速度非常快,不会计算相关度直接跳过了整个评分阶段而且很容易被缓存。查询主要的应用场景就是进行全文搜索。目前为止还挺好。类似方式的搜索多带带写一个方法,并可以支持高亮显示搜索词。

1、结构化搜索 1.1 精确值查找

过滤器很重要,因为它们执行速度非常快,不会计算相关度(直接跳过了整个评分阶段)而且很容易被缓存。请尽可能多的使用过滤式查询。

term 查询会查找我们指定的精确值。作为其本身, term 查询是简单的。它接受一个字段名以及我们希望查找的数值:
{

"term" : {
    "price" : 20
}

}

通常当查找一个精确值的时候,我们不希望对查询进行评分计算。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分。因为在查询时,不需要计算评分,因此采用constant_score寻找的方式速度会更快。
最终组合的结果是一个 constant_score 查询,它包含一个 term 查询:

GET /my_store/products/_search
{
  "query" : {
      "constant_score" : { 
          "filter" : {
              "term" : { 
                  "price" : 20
              }
          }
      }
  }
}
1.2 组合过滤器 1.2.1 布尔过滤器
{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

must
所有的语句都 必须(must) 匹配,与 AND 等价。
must_not
所有的语句都 不能(must not) 匹配,与 NOT 等价。
should
至少有一个语句要匹配,与 OR 等价。


GET /my_store/products/_search
{
   "query" : {
      "filtered" : { 
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
         }
      }
   }
}
1.2.2 嵌套布尔过滤器
SELECT document
FROM   products
WHERE  productID      = "KDKE-B-9947-#kL5"
  OR (     productID = "JODL-X-1937-#pV7"
       AND price     = 30 )

GET /my_store/products/_search
{
   "query" : {
      "filtered" : {
         "filter" : {
            "bool" : {
              "should" : [
                { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, 
                { "bool" : { 
                  "must" : [
                    { "term" : {"productID" : "JODL-X-1937-#pV7"}}, 
                    { "term" : {"price" : 30}} 
                  ]
                }}
              ]
           }
         }
      }
   }
}
1.3 查找多个精确值
如果我们想要查找价格字段值为 $20 或 $30 的文档该如何处理呢?
GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "terms" : { 
                    "price" : [20, 30]
                }
            }
        }
    }
}
1.4 范围
gt: > 大于(greater than)
lt: < 小于(less than)
gte: >= 大于或等于(greater than or equal to)
lte: <= 小于或等于(less than or equal to)

GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "range" : {
                    "price" : {
                        "gte" : 20,
                        "lt"  : 40
                    }
                }
            }
        }
    }
}

如果想要范围无界(比方说 >20 ),只须省略其中一边的限制:
"range" : {
    "price" : {
        "gt" : 20
    }
}

日期范围
"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-07 00:00:00"
    }
}

当使用它处理日期字段时, range 查询支持对 日期计算(date math) 进行操作,比方说,如果我们想查找时间戳在过去一小时内的所有文档:
"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" 
    }
}
1.5 处理null值 1.5.1 存在查询
SELECT tags
FROM   posts
WHERE  tags IS NOT NULL

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}
1.5.2.缺失查询
SELECT tags
FROM   posts
WHERE  tags IS NULL

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "missing" : { "field" : "tags" }
            }
        }
    }
}
2、 全文搜索 2.1 匹配查询

match 是个 核心 查询。无论需要查询什么字段, match 查询都应该会是首选的查询方式。 它是一个高级 全文查询 ,这表示它既能处理全文字段,又能处理精确字段。match 查询主要的应用场景就是进行全文搜索。

2.1.1. 单个词查询
GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}
2.1.2 多个词查询
GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

用 任意 查询词项匹配文档可能会导致结果中出现不相关的长尾。 这是种散弹式搜索。可能我们只想搜索包含 所有 词项的文档,也就是说,不去匹配 brown OR dog ,而通过匹配 brown AND dog 找到所有文档。

match 查询还可以接受 operator 操作符作为输入参数,默认情况下该操作符是 or 。我们可以将它修改成 and 让所有指定词项都必须匹配:

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {      
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}
2.2 组合查询
GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}
2.3 控制精度

就像我们能控制 match 查询的精度 一样,我们可以通过 minimum_should_match 参数控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比:

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 
    }
  }
}

这个查询结果会将所有满足以下条件的文档返回: title 字段包含 "brown" AND "fox" 、 "brown" AND "dog" 或 "fox" AND "dog" 。如果有文档包含所有三个条件,它会比只包含两个的文档更相关。

2.4 查询语句提升权重

假设想要查询关于 “full-text search(全文搜索)” 的文档, 但我们希望为提及 “Elasticsearch” 或 “Lucene” 的文档给予更高的 权重 ,这里 更高权重 是指如果文档中出现 “Elasticsearch” 或 “Lucene” ,它们会比没有的出现这些词的文档获得更高的相关度评分 _score ,也就是说,它们会出现在结果集的更上面。

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { 
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ 
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}


should 语句匹配得越多表示文档的相关度越高。目前为止还挺好。

但是如果我们想让包含 Lucene 的有更高的权重,并且包含 Elasticsearch 的语句比 Lucene 的权重更高,该如何处理?

我们可以通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。所以下面重写之前的查询:
GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}
3、展望

在使用ES的过程中在网上搜到了一些ES封装的第三方扩展类,但并未找到在项目中对第三方扩展类进一步封装更加友好地在项目中使用的PHP封装类,因此打算自定义一个ES服务类,目前正在开发中,因而熟悉文档并进行归纳总结便是第一步,接下来完成之后便更新发布。目前的思路为对于常用的查询操作,封装一个方法即可,并支持传入参数查询字段、排序,分页。类似like方式的搜索多带带写一个方法,并可以支持高亮显示搜索词。对于复杂的可直接支持原生方式查询。

附录

参考文档地址

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/34519.html

相关文章

  • 搜索引擎选择: Elasticsearch与Solr,elasticsearch是什么

    摘要:完全支持的接近实时的搜索。是最流行的企业级搜索引擎,还增加了支持。采用了搜索库为核心的全文索引和搜索,并具有类似的和的。不考虑建索引的同时进行搜索,速度更快。缺点只是搜索方案,建索引部分还是需要自己实现。在搜索功能上,只实现了最基本的需求。 Elasticsearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。 它可以...

    darkbug 评论0 收藏0
  • elasticsearch学习笔记(二)——elasticsearch的功能、适用场景以及特点介绍

    摘要:比如有个大型商场集团,,分析一下某某地区最近年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表。 学习了什么是Elasticsearch之后,针对工程而言,我们更加关心的是Elasticsearch它能干什么?能在什么地方发挥作用?跟其它类似的东西相比它不同的地方在哪里?归纳起来就是Elasticsearch在什么场景下,相比于其他类似的技术而言,它更适合做什么 1、El...

    宋华 评论0 收藏0
  • Elasticsearch * 入门

    摘要:和使用倒排索引的数据结构来达到相同目的。无需配置,只需要添加数据然后开始搜索分布式的特性你不需要知道任何关于分布式系统分片集群发现或者其他大量的分布式概念。致力于隐藏分布式系统的复杂性。 Elasticsearch * 入门 1. Elasticsearch 前言 Elasticsearch 是一个基于Apache Lucene(TM)的开源搜索引擎、实时分布式搜索和分析引擎。 Lu...

    zengdongbao 评论0 收藏0
  • Elasticsearch简介与实战

    摘要:由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引。能够实现快速高效的搜索功能,正是基于倒排索引原理。 什么是Elasticsearch? showImg(https://segmentfault.com/img/remote/1460000018407522);   Elasticsearch是一个开源的分布式、RESTful 风格的搜索和数据分析引擎,它的底...

    Anleb 评论0 收藏0
  • Elasticsearch检索实战

    摘要:检索中需包含索引名,为查询关键字。说明后续将使用对比语法进行搜索条件示例。结构化查询结构化查询支持全文检索,会对检索结果进行相关性计算。聚合该部分较复杂,已单独使用文章进行说明,见检索聚合和部分。 首发于 樊浩柏科学院 随着公司房源数据的急剧增多,现搜索引擎 Solr 的搜索效率和建立索引效率显著降低,而 Elasticsearch 是一个实时的分布式搜索和分析引擎,它是基于全文搜索...

    android_c 评论0 收藏0

发表评论

0条评论

googollee

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<