elasticsearch笔记_精确值搜索_filter(四)
来源:互联网 发布:如何做合格淘宝客服 编辑:程序博客网 时间:2024/05/16 14:39
过滤器搜索(filter)
结构化搜索(Structured search): 是指有关探询具有内在结构数据的过程。比如日期、时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作。比较常见的操作包括比较数字或时间的范围,或判定两个值的大小。
注意:对于结构化文本来说,一个值要么相等,要么不等.
由于是结构化查询 , 下面会类比sql语句:
1.term查询数字
select document from products where price = 20
对于精确查找 , 用term实现:
{ "term" : { "price" : 20 }}
在不想被评分(不评分可以提高效率)的时候 , 将term查找转化为过滤器 , constant_score表示可以使term查询以非评分(其实是统一评分 , 结果的_score都是1.0)的方式进行查询 :
GET /my_store/products/_search{ "query" : { "constant_score" : { "filter" : { "term" : { "price" : 20 } } } }}
2.term文本查找
select product from products where productId="XHDK-A-1293-#fJ3"
直接用刚才的term精确查找 , 不会得到预期结果,原因是elasticsearch底层的倒排索引 , 将文本查询进行分析 , 并拆分成词条 。 查询一下被分析的结果:
GET /my_store/_analyze{ "field": "productID", "text": "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 } ]}
为了使查询的关键字不被分析 , 得告诉Elasticsearch这个productId是不被分析的 , 即not_analyzed , 只能更改索引(注意:elasticsearch里面的索引一旦创建不能被修改 , 只能被删除和重新创建) 。
更改索引:
删除原来的索引:DELETE /my_store 我们可以创建新的索引并为其指定自定义映射:PUT /my_store { "mappings" : { "products" : { "properties" : { "productID" : { "type" : "string", "index" : "not_analyzed" } } } }}
此时再进行刚才的term查询,会得到与productId完全匹配的预期结果 。
3.Elasticsearch 会在运行非评分查询的时执行多个操作:
(1)查找匹配文档 。 在倒排索引中查找 XHDK-A-1293-#fJ3 然后获取包含该 term 的所有文档。
(2)创建 bitset 。(bitset是一个只存0或1的数组),描述了有哪些文档被term到了(比如:如果有4个文档,文档2被term匹配到了,bitset就是[0,1,0,0])
(3)迭代 bitset(s) 。 Elasticsearch会为每一个查询条件都生成一个bitset,这些bitset构成了一个bitsets。Elasticsearch 就会循环迭代 bitsets 从而找到满足所有过滤条件的匹配文档的集合。在内部,它表示成一个 “roaring bitmap”,可以同时对稀疏或密集的集合进行高效编码。通常会先迭代稀疏的bitset,因为这样就会首先排除大量的文档。
(4)增量使用计数 。 Elasticsearch会缓存非评分查询,如果查询在最近的 256 次查询中会被用到,那么它就会被缓存到内存中。
4.组合过滤器
select product from products where (price = 20 OR productID = "XHDK-A-1293-#fJ3") AND (price != 30)
需要用到bool过滤器 : bool里面的关键字与sql里面的关键字对应(and–>must ; or—>should ; not—>must_not)
GET /my_store/products/_search{ "query" : { "filtered" : { "filter" : { "bool" : { "should" : [ { "term" : {"price" : 20}}, { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} ], "must_not" : { "term" : {"price" : 30} } } } } }}
注意:组合过滤器需要用filtered套在外面.
5.嵌套过滤器
select document from products where 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}} ] }} ] } } } }}
6.查找多个精确值
select document from products where price in (20,30);
GET /my_store/products/_search{ "query" : { "constant_score" : { "filter" : { "terms" : { "price" : [20, 30] } } } }}
注意 : 上面用的是terms , 注意term 和 terms的区别.term相当于sql里面的”=” , terms相当于sql里面的in .
7.范围查找
select document from products where price between 20 and 40;
GET /my_store/products/_search{ "query" : { "constant_score" : { "filter" : { "range" : { "price" : { "gte" : 20, "lt" : 40 } } } } }}
特殊字符代表的意义:
gt : > 大于(greater than)
lt : < 小于(less than)
gte : >= 大于或等于(greater than or equal to)
lte : <= 小于或等于(less than or equal to)
如果是查询日期字段的时候,将上面的过滤器里面的range换成如下:
"range" : { "timestamp" : { "gt" : "2014-01-01 00:00:00", "lt" : "2014-01-07 00:00:00" }}"range" : { "timestamp" : { "gt" : "now-1h" //过去一小时. }}"range" : { "timestamp" : { "gt" : "2014-01-01 00:00:00", "lt" : "2014-01-01 00:00:00||+1M" //在这个时间的基础上再加1个月. }}
范围查找也支持字符串(字典顺序)范围:
"range" : { "title" : { "gte" : "a", "lt" : "b" }}
注意 : Elasticsearch 实际上是在为范围内的每个词项都执行 term 过滤器,这会比日期或数字的范围过滤慢许多。
8.关于null值
在elasticsearch里面 , 如果字段不存在,那么它也不会持有任何 token(倒排索引里面的词条)。null [](空数组)和 [null] 所有这些都是等价的,它们无法存于倒排索引中。
select tags from posts where tags is not null;
GET /my_index/posts/_search{ "query" : { "constant_score" : { "filter" : { "exists" : { "field" : "tags" } } } }}
select tags from posts where tags is null;
GET /my_index/posts/_search{ "query" : { "constant_score" : { "filter": { "missing" : { "field" : "tags" } } } }}
关于自定义对象的null :
{ "name" : { "first" : "John", "last" : "Smith" }}
实际上是这样存储的 :
{ "name.first" : "John", "name.last" : "Smith"}
所以用 exists 或 missing 查询 name 字段时 :
{ "exists" : { "field" : "name" }}
实际上执行的是 :
{ "bool": { "should": [ { "exists": { "field": "name.first" }}, { "exists": { "field": "name.last" }} ] }}
如果 first 和 last 都是空,那么 name 这个命名空间才会被认为不存在 .
9.关于缓存
elasticsearch对非评分查询是有缓存的 , 并且缓存的值是bitset , 并且是以增量的形式更新的( 例如新添加一个文档 , 只需将那些新文档加入已有 bitset , 而不是对整个缓存一遍又一遍的重复计算。)
于是就会有下面两种bool查询会使用同一 bitset .
让我们看看下面例子中的查询,它查找满足以下任意一个条件的电子邮件:(1)在收件箱中,且没有被读过的.(2)不在 收件箱中,但被标注重要的.GET /inbox/emails/_search{ "query": { "constant_score": { "filter": { "bool": { "should": [ { "bool": { "must": [ { "term": { "folder": "inbox" }}, { "term": { "read": false }} ] }}, { "bool": { "must_not": { "term": { "folder": "inbox" } }, "must": { "term": { "important": true } } }} ] } } } }}
如果一个非评分查询在最近的 256 词查询中被使用过(次数取决于查询类型),那么这个查询就会作为缓存的候选。但是,并不是所有的片段都能保证缓存 bitset 。只有那些文档数量超过 10,000 (或超过总文档数量的 3% )才会缓存 bitset 。因为小的片段可以很快的进行搜索和合并,这里缓存的意义不大。
一旦缓存了,非评分计算的 bitset 会一直驻留在缓存中直到它被剔除。剔除规则是基于 LRU 的:一旦缓存满了,最近最少使用的过滤器会被剔除。
- elasticsearch笔记_精确值搜索_filter(四)
- elasticsearch笔记_全文搜索_query(五)
- elasticsearch笔记_多字段搜索(六)
- Java精选笔记_Filter(过滤器)
- Elasticsearch服务器 搜索笔记
- [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段
- [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段
- 【lodash-学习01】-_.findIndex(),_filter()
- elasticsearch笔记_基本概念(一)
- elasticsearch笔记_基本概念(一)
- ElasticSearch学习29_基于Elasticsearch实现搜索推荐
- [ElasticSearch]精确值与全文文本
- ElasticSearch 攻略(四)简易搜索
- [Elasticsearch] 多字段搜索 (四) - 跨字段实体搜索
- [Elasticsearch] 多字段搜索 (四) - 跨字段实体搜索
- 精确搜索
- Elasticsearch服务器 更好的搜索笔记
- elasticsearch笔记_相关度控制(八)
- 算法竞赛入门经典(第2版)习题2-4
- tessnet2和3版本混用后程序错误的解决
- js中cssText批量修改元素样式
- 百度地图开发(二)--定位,lbs数据查询,路径规划
- Android中判断是否有网络连接以及网络监控状态
- elasticsearch笔记_精确值搜索_filter(四)
- Python 2.7与Python3 的print有什么区别?
- 【OpenCV3】基于双目视觉的三维重建
- C# System.NullReferenceException: 未将对象引用设置到对象的实例
- ProduceQueue;支持堵塞和非堵塞
- 高并发Java 三 Java内存模型和线程安全
- 文件IO编程十一
- sql创建表、删除表、删除字段、增加字段
- iOS开发之蓝牙通讯