ElasticSearch常用结构化搜索
最近,需要用到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常用结构化搜索的更多相关文章
- elasticsearch 深入 —— 结构化搜索
		结构化搜索 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作.比较常见的操作 ... 
- Elasticsearch系列---结构化搜索
		概要 结构化搜索针对日期.时间.数字等结构化数据的搜索,它们有自己的格式,我们可以对它们进行范围,比较大小等逻辑操作,这些逻辑操作得到的结果非黑即白,要么符合条件在结果集里,要么不符合条件在结果集之外 ... 
- ElasticSearch 2 (13) - 深入搜索系列之结构化搜索
		ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ... 
- ElasticSearch 结构化搜索
		1.介绍 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作. 比较常见的操作 ... 
- ElasticStack学习(九):深入ElasticSearch搜索之词项、全文本、结构化搜索及相关性算分
		一.基于词项与全文的搜索 1.词项 Term(词项)是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term. Term的使用说明: 1)Term Level Query:Ter ... 
- Elasticsearch结构化搜索与查询
		Elasticsearch 的功能之一就是搜索,搜索主要分为两种类型,结构化搜索和全文搜索.结构化搜索是指有关查询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可 ... 
- Elasticsearch 结构化搜索、keyword、Term查询
		前言 Elasticsearch 中的结构化搜索,即面向数值.日期.时间.布尔等类型数据的搜索,这些数据类型格式精确,通常使用基于词项的term精确匹配或者prefix前缀匹配.本文还将新版本的&qu ... 
- ElasticSearch 结构化搜索全文
		1.介绍 上篇介绍了搜索结构化数据的简单应用示例,现在来探寻 全文搜索(full-text search) :怎样在全文字段中搜索到最相关的文档. 全文搜索两个最重要的方面是: 相关性(Relevan ... 
- ElasticSearch(6)-结构化查询
		引用:ElasticSearch权威指南 一.请求体查询 请求体查询 简单查询语句(lite)是一种有效的命令行_adhoc_查询.但是,如果你想要善用搜索,你必须使用请求体查询(request bo ... 
随机推荐
- poj-3278    catch that cow(搜索题)
			题目描述: Farmer John has been informed of the location of a fugitive cow and wants to catch her immedia ... 
- Codeforces Round #505 D. Recovering BST(区间DP)
			首先膜一发网上的题解.大佬们tql. 给你n个单调递增的数字,问是否能够把这些数字重新构成一棵二叉搜索树(BST),且所有的父亲结点和叶子结点之间的gcd > 1? 这个题场上是想暴力试试的.结 ... 
- 第十四届华中科技大学程序设计竞赛决赛同步赛    	Beautiful Land
			It’s universally acknowledged that there’re innumerable trees in the campus of HUST.Now HUST got a b ... 
- Linux学习-YUM 在线升级机制
			这个 yum 是透过分析 RPM 的标头资料后, 根据 各软件的相关性制作出属性相依时的解决方案,然后可以自动处理软件的相依属性问题,以解决软件 安装或移除与升级的问题. 利用 yum 进行查询.安装 ... 
- web安全测试---AppScan扫描工具(转)
			安全测试应该是测试中非常重要的一部分,但他常常最容易被忽视掉. 尽管国内经常出现各种安全事件,但没有真正的引起人们的注意.不管是开发还是测试都不太关注产品的安全.当然,这也不能怪我们苦B的“民工兄弟” ... 
- python 学习分享-字典篇
			python字典(Dictionary) dict是无序的 key必须是唯一切不可变的 a={'key1':'value1','key2':'value2'} 字典的增删改查 a['key3']='v ... 
- ccna 闫辉单臂路由 和 acl access control list
			ccna 闫辉单臂路由 和 acl access control list 一单臂路由 当前园区网设计很少用到 成本低 小型的.局域网可用 二ACL acc ... 
- [错误处理]Vim卡死,无法输入是怎么回事?是不是按了Ctrl+S
			在linux下使用终端的时候常常不经意的就僵死了,只能够重启来解决这个问题,后来发现常常是因为按了Ctrl+s. 经过查询Ctrl + s在终端下的含义是暂停使用该终端的用途,如果需要启用终端,需要按 ... 
- Python杂技
			py转exe文件 用 pyinstaller,可以把所有文件打包成一个单独的exe文件 win10X64 =>pip install pyinstaller pyinstaller [参数] [ ... 
- Android中动态改变控件的大小的一种方法
			在Android中有时候我们需要动态改变控件的大小.有几种办法可以实现 一是在onMeasure中修改尺寸,二是在onLayout中修改位置和尺寸.这个是可以进行位置修改的,onMeasure不行. ... 
