ElasticSearch结构化搜索和全文搜索

https://segmentfault.com/a/1190000019753737?utm_source=tag-newest

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.cnblogs.com/xiaohanlin/p/12342500.html

时间: 2024-08-07 10:37:14

ElasticSearch结构化搜索和全文搜索的相关文章

ElasticSearch结构化查询

ElasticSearch结构化查询 Elasticsearch 提供了丰富的查询过滤语句,而有一些是我们较常用到的. 现在我们快速的介绍一下 这些最常用到的查询过滤语句. term 过滤 term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型): { "term": { "age": 26 }} { "term": { "date": "2014-09-0

ElasticSearch 结构化搜索全文

1.介绍 上篇介绍了搜索结构化数据的简单应用示例,现在来探寻 全文搜索(full-text search) :怎样在全文字段中搜索到最相关的文档. 全文搜索两个最重要的方面是: 相关性(Relevance) 它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法(参见 相关性的介绍).地理位置邻近.模糊相似,或其他的某些算法. 分析(Analysis) 它是将文本块转换为有区别的.规范化的 token 的一个过程,(参见 分析的介绍) 目

全文搜索原理简单解析

文前声明:本人只是知识的搬运工,文中许多知识和观点大多数都是来自于网络或书本,因为没有记录的习惯学习研究完,便忘记名称了,如若还记得,在文后自会添加备注. 注:这是本人的第一篇薄文,水平相形见拙,有错误之处,欢迎指正. 今年的计划是存储领域,希望能深入的了解其原理,如果能有创造性的写出一个自己的文件系统出来就更好了,到目前为止尚无动工的迹象,估计会顺延至明年了吧! 我的计划正好赶上公司的总规划,于是便接了“大数据”的活.刚开始进入这一行,走了不少弯路,说多了都是泪(这不是本文的主题,就此打住,后

全文搜索-介绍-elasticsearch-definitive-guide翻译

全文搜索 我们通过前文的简单例子,已经了解了结构化数据的条件搜索:现在,让我们来了解全文搜索-- 怎样通过匹配所有域的文本找到最相关的文章. 关于全文搜索有两个最重要的方面: 相似度计算 通过TF/IDF (see [relevance-intro]),地理位置接近算法,模糊相似度算法或者其他算法,用来给给定查询条件的结果排序. 文本分析 通过把文本切割和归一化后的词元,去(a)生成倒排索引,或者去(b)查询倒排索引. 当我们在讨论相似度计算和文本分析的时候,我们只是在讨论查询,而不是过滤 词条

全文搜索基本原理(倒排索引、搜索结果排序)

总结:全文搜索可以认为是搜索引擎最重要的功能,很多系统(如Luence)也支持全文搜索.全文搜索背后涉及的最重要的原理有两个:倒排索引.搜索结果排序 1.倒排索引: 给定若干搜索词 {Ti},可以根据倒排索引快速搜得相关的文档 {Di}. 2.搜索结果排序(文档排序),主要思想是先找出搜索词扮重要作用的文档(定评价标准),接着通过比较作用的大小来排序(通过评价标准评价).分两步: 2.1.找出各搜索词在各搜得的文档内的权重Wtd,从而得到搜得的每个文档的搜索词权重向量 2.2.将各搜索词也看做一

结构化、半结构化和非结构化数据

在实际应用中,我们会遇到各式各样的数据库如nosql非关系数据库(memcached,redis.mangodb).RDBMS关系数据库(oracle,mysql等),另一些其他的数据库如hbase,在这些数据库中.又会出现结构化数据.非结构化数据.半结构化数据,以下列出各种数据类型: 结构化数据: 可以用数据或统一的结构加以表示,我们称之为结构化数据,如数字.符号.传统的关系数据模型.行数据,存储于数据库,可用二维表结构表示. 半结构化数据: 所谓半结构化数据.就是介于全然结构化数据(如关系型

[转]结构化、半结构化和非结构化数据

在实际应用中,我们会遇到各式各样的数据库如nosql非关系数据库(memcached,redis,mangodb),RDBMS关系数据库(oracle,mysql等),还有一些其它的数据库如hbase,在这些数据库中,又会出现结构化数据,非结构化数据,半结构化数据,下面列出各种数据类型: 结构化数据: 能够用数据或统一的结构加以表示,我们称之为结构化数据,如数字.符号.传统的关系数据模型.行数据,存储于数据库,可用二维表结构表示.   半结构化数据: 所谓半结构化数据,就是介于完全结构化数据(如

什么是结构化数据?什么是半结构化数据?

概述 相对于结构化数据(即行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据)而言,不方便用数据库二维逻辑表来表现的数据即称为非结构化数据,包括所有格式的办公文档.文本.图片.XML.HTML.各类报表.图像和音频/视频信息等等. 非结构化数据库是指其字段长度可变,并且每个字段的记录又可以由可重复或不可重复的子字段构成的数据库,用它不仅可以处理结构化数据(如数字.符号等信息)而且更适合处理非结构化数据(全文文本.图象.声音.影视.超媒体等信息). 非结构化WEB数据库主要是针对非结构化

ElasticSearch常用结构化搜索

最近,需要用到ES的一些常用的结构化搜索命令,因此,看了一些官方的文档,学习了一下.结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的. 它们都有精确的格式,我们可以对这些数据进行逻辑操作,比较常见的操作包括比较时间区间,或者获取两个数字间的较大值. 精确查询 当进行精确查询时,过滤器filter是十分重要的,因为它们效率非常高,过滤器不计算相关性(直接跳过了整个记分阶段)而且很容易进行缓存. 过滤数字 我们首先看 term filter,它最常用,可以用来处理数字,布