ElasticSearch常用结构化搜索

时间:2022-08-27 20:25:39

最近,需要用到ES的一些常用的结构化搜索命令,因此,看了一些官方的文档,学习了一下。结构化查询指的是查询那些具有内在结构的数据,比如日期、时间、数字都是结构化的。

它们都有精确的格式,我们可以对这些数据进行逻辑操作,比较常见的操作包括比较时间区间,或者获取两个数字间的较大值。

精确查询

当进行精确查询时,过滤器filter是十分重要的,因为它们效率非常高,过滤器不计算相关性(直接跳过了整个记分阶段)而且很容易进行缓存。

过滤数字

我们首先看 term filter,它最常用,可以用来处理数字,布尔值,日期和文本。

例如我们有一些产品:

POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }

我们想要做的是要查询具有某个价格的所有产品,如果对于SQL熟悉,那么它的表达式是:

SELECT * FROM   products WHERE  price = 20

在ES查询中,我们使用 term 达到相同的目的:

{
"term" : {
"price" : 20
}
}

但是在ES里,term 不能单独使用,search API期望的是一个 query 而不是 filter,所以,我们需要把 term 放在一个filter query里进行使用:

GET /my_store/products/_search
{
"query" : {
"filtered" : { #filtered 查询同时接受一个 query 和 filter
"query" : {
"match_all" : {} #match_all 会返回所有匹配的文件,这是个默认行为
},
"filter" : {
"term" : { #term 过滤我们之前说到的,需要注意的是这里 term块 是处于 filter 之内的
"price" : 20
}
}
}
}
}

执行结果正如我们期望一样,它只会返回文档2,这里我们称为命中hit。

"hits" : [
{
"_index" : "my_store",
"_type" : "products",
"_id" : "2",
"_score" : 1.0, #1
"_source" : {
"price" : 20,
"productID" : "KDKE-B-9947-#kL5"
}
}
]

之前我们说到filter不会进行记分或相关性计算,这里的分数来自于我们查询时使用的关键字 match_all ,它会同等对待所有的文件,并对所有的结果都给以1的记分。

过滤文本

term 同样可以用来过滤文本,如果我们想要查询某个具体UPC id的产品,SQL语句会是下面这样:

SELECT product FROM   products WHERE  productID = "XHDK-A-1293-#fJ3"

转换成ES查询,同样使用 term 来查询:

GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"term" : {
"productID" : "XHDK-A-1293-#fJ3"
}
}
}
}
}

但这里有个小问题,我们没有如预期得到想要的结果!为什么呢?问题并不出在 term 查询上,问题出在数据索引的方式。如果使用 analyze API(Test Analyzers),我们可以看到这里的UPC码以及被拆分成多个小的token:

GET /my_store/_analyze?field=productID
XHDK-A-1293-#fJ3

结果

{
"tokens" : [ {
"token" : "xhdk",
"start_offset" : 0,
"end_offset" : 4,
"type" : "<ALPHANUM>",
"position" : 1
}, {
"token" : "a",
"start_offset" : 5,
"end_offset" : 6,
"type" : "<ALPHANUM>",
"position" : 2
}, {
"token" : "1293",
"start_offset" : 7,
"end_offset" : 11,
"type" : "<NUM>",
"position" : 3
}, {
"token" : "fj3",
"start_offset" : 13,
"end_offset" : 16,
"type" : "<ALPHANUM>",
"position" : 4
} ]
}

所以,当我们用 term 去过滤值 XHDK-A-1293-#fJ3 的时候,找不到任何文件,因为这个token不在我们的反向索引(inverted index)之中,正如上面呈现的,索引里面有4个token。

显然,这种对于id码或其他任何精确值的处理方式不是我们想要的。

为了避免这种问题,我们需要告诉ElasticSearch这个字段具有精确值,需要被设置成 not_analyzed 。 我们可以在定制化字段mapping中找到相关内容。为了修正这个问题,我们需要首先删除老的index,然后再创建一个新的

DELETE /my_store #1

PUT /my_store #2
{
"mappings" : {
"products" : {
"properties" : {
"productID" : {
"type" : "string",
"index" : "not_analyzed" #3
}
}
}
} }

然后我们就可以对文件重索引了:

POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }

组合过滤器

上面的两个例子都是单个filter的使用方式,在实际中,我们很多情况下会同时会对多个值或字段使用filter。例如,在ElasticSearch中,如何标识下面这个SQL?

SELECT product FROM   products WHERE  (price = 20 OR productID = "XHDK-A-1293-#fJ3") AND  (price != 30)

在这种情况下,我们需要 bool filter。这是一个复合过滤器可以接收多个参数,然后将他们组合成布尔组合。

布尔过滤器(Bool Filter)

bool filter包括三部分:

{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
}
}
  • must:所有的语句必须匹配,与 AND 等价。

  • must_not:所有的语句都不能匹配,与 NOT 等价。

  • should:至少有一个语句匹配,与 OR 等价。

用ES查询实现我们上面SQL里的查询:

GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}

我们搜索的结果返回了2个hits,两个文件各满足其中一个条件:

"hits" : [
{
"_id" : "1",
"_score" : 1.0,
"_source" : {
"price" : 10,
"productID" : "XHDK-A-1293-#fJ3"
}
},
{
"_id" : "2",
"_score" : 1.0,
"_source" : {
"price" : 20,
"productID" : "KDKE-B-9947-#kL5"
}
}
]

嵌套布尔过滤器(Nesting Boolean Filters)

尽管 bool 是一个复合的过滤器,可以接受多个子过滤器,需要注意的是 bool 过滤器本身仍然是一个过滤器(filter)。这意味着我们可以将一个bool过滤器置于另外一个bool过滤器内部,这为我们提供了复杂布尔逻辑的处理能力:

对于一个SQL语句:

SELECT document FROM   products WHERE  productID  = "KDKE-B-9947-#kL5" OR ( productID = "JODL-X-1937-#pV7" AND price = 30 )

我们将其转换成一个嵌套的 bool 过滤器:

GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"productID" : "KDKE-B-9947-#kL5"}}, #1
{ "bool" : { #2
"must" : [
{ "term" : {"productID" : "JODL-X-1937-#pV7"}}, #3
{ "term" : {"price" : 30}} #4
]
}}
]
}
}
}
}
}

得到的结果有两个文件,他们各满足 should 中的一个条件:

"hits" : [
{
"_id" : "2",
"_score" : 1.0,
"_source" : {
"price" : 20,
"productID" : "KDKE-B-9947-#kL5" #1
}
},
{
"_id" : "3",
"_score" : 1.0,
"_source" : {
"price" : 30, #2
"productID" : "JODL-X-1937-#pV7" #3
}
}
]

ElasticSearch常用结构化搜索的更多相关文章

  1. elasticsearch 深入 —— 结构化搜索

    结构化搜索 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作.比较常见的操作 ...

  2. Elasticsearch系列---结构化搜索

    概要 结构化搜索针对日期.时间.数字等结构化数据的搜索,它们有自己的格式,我们可以对它们进行范围,比较大小等逻辑操作,这些逻辑操作得到的结果非黑即白,要么符合条件在结果集里,要么不符合条件在结果集之外 ...

  3. ElasticSearch 2 &lpar;13&rpar; - 深入搜索系列之结构化搜索

    ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ...

  4. ElasticSearch 结构化搜索

    1.介绍 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作. 比较常见的操作 ...

  5. ElasticStack学习(九):深入ElasticSearch搜索之词项、全文本、结构化搜索及相关性算分

    一.基于词项与全文的搜索 1.词项 Term(词项)是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term. Term的使用说明: 1)Term Level Query:Ter ...

  6. Elasticsearch结构化搜索与查询

    Elasticsearch 的功能之一就是搜索,搜索主要分为两种类型,结构化搜索和全文搜索.结构化搜索是指有关查询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可 ...

  7. Elasticsearch 结构化搜索、keyword、Term查询

    前言 Elasticsearch 中的结构化搜索,即面向数值.日期.时间.布尔等类型数据的搜索,这些数据类型格式精确,通常使用基于词项的term精确匹配或者prefix前缀匹配.本文还将新版本的&qu ...

  8. ElasticSearch 结构化搜索全文

    1.介绍 上篇介绍了搜索结构化数据的简单应用示例,现在来探寻 全文搜索(full-text search) :怎样在全文字段中搜索到最相关的文档. 全文搜索两个最重要的方面是: 相关性(Relevan ...

  9. ElasticSearch&lpar;6&rpar;-结构化查询

    引用:ElasticSearch权威指南 一.请求体查询 请求体查询 简单查询语句(lite)是一种有效的命令行_adhoc_查询.但是,如果你想要善用搜索,你必须使用请求体查询(request bo ...

随机推荐

  1. CSS中使用text-transform实现首字母大写

    CSS中首字母大写怎么实现?日常生活中需求方对英文的要求比较多,有的时候需要让英文单词或拼音首个字母大写;有的时候需要让全文中英文单词全大写或小写.这时候我们就需要text-transform属性了. ...

  2. &lbrack;bzoj1597&rsqb;&lbrack;usaco2008 mar&rsqb;土地购买 &lpar;动态规划&plus;斜率优化&rpar;

    Description 农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000, ...

  3. js数组合并

    // 第一种 var mergeTo = [4,5,6], mergeFrom = [7,8,9]; mergeTo = mergeTo.concat(mergeFrom); mergeTo; // ...

  4. Java集群优化——使用Dubbo对单一应用服务化改造

    之前,我们讨论过Nginx+tomcat组成的集群,这已经是非常灵活的集群技术,但是当我们的系统遇到更大的瓶颈,全部应用的单点服务器已经不能满足我们的需求,这时,我们要考虑另外一种,我们熟悉的内容,就 ...

  5. STM32应用实例五:与SHT1X温湿度传感器通讯

    在这次项目开发中应用到了SHT1X温湿度传感器,该系列有SHT10.SHT11和SHT15,属于Sersirion温湿度传感器家族中的贴片封装系列.包括一个电容性聚合体测湿敏感元件.一个用能隙材料制成 ...

  6. Python爬虫技巧

    Python爬虫技巧一之设置ADSL拨号服务器代理 reference: https://zhuanlan.zhihu.com/p/25286144 爬取数据时,是不是只能每个网站每个网站的分析,有没 ...

  7. OTL翻译&lpar;1&rpar; -- 说明

    说明 该文档说明的是4.0版本的ORACLE/ODBC和DB2-CLI模板库(OTL).OTL4.0(后面简称OTL)模板库是基于C++的模板的. OTL4.0是组合了C++的模板框架和OTL适配器. ...

  8. Linux磁盘及文件系统(三)Linux文件系统

    一.文件系统的组成 Linux常见的文件系统类型有ReiserFS,ext2,ext3,ext4,vfat,XFS等,文件系统是对一个存储设备上数据和元数据进行组织的机制.他的最终目的是把大量数据有组 ...

  9. 海思hi3518 opencv测试

    2.4.9的opencv 安装好交叉编译后,用Cmake 配置opencv 修改CMakeCache.txtCMAKE_EXE_LINKER_FLAGS:STRING=-lpthread -lrt - ...

  10. Codeforces Round &num;277&period;5 &lpar;Div&period; 2&rpar;D Unbearable Controversy of Being (暴力)

    这道题我临场想到了枚举菱形的起点和终点,然后每次枚举起点指向的点,每个指向的点再枚举它指向的点看有没有能到终点的,有一条就把起点到终点的路径个数加1,最后ans+=C(路径总数,2).每两个点都这么弄 ...