分布式搜索引擎Elasticsearch的查询与过滤
Posted 邱明成
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式搜索引擎Elasticsearch的查询与过滤相关的知识,希望对你有一定的参考价值。
一、写入
先来一个简单的官方例子,插入的参数为
-XPUT
,插入一条记录。
curl -XPUT‘http://localhost:9200/test/users/1‘ -d‘{ "user": "test", "post_date": "2009-11-15T14:12:12", "message": "Elastic Search" }‘ { "_index": "test", "_type": "users", "_id": "1", "_version": 2, "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": false }
从上面的这个例子中,可以看出ES的http的服务的默认端口9200,后面的
/test/users/1
是这条记录的索引部分,体现了它的RESTful风格
这三级目录分布对应了
_index,
_type,
_id
实际上ES上存放的所有的记录都只能通过三级目录的方式找到
_id
字段可以是数字也可以是字符串。在执行上面的命令时ES会自动创建这些索引
-d
后面跟上了要插入的json格式的记录
-XPUT
表明这是插入一条数据,ES中叫创建一个索引
_version
字段,表明了当前记录的版本号,当你想这个索引重新put一条记录时,版本号会自动加一
二、删除
删除的http请求参数为
-XDELETE
,通过下面的命令可以删除这条记录:
curl -XDELETE ‘http://localhost:9200/test/users/1?pretty‘ { "found" : true, "_index" : "test", "_type" : "users", "_id" : "1", "_version" : 3, "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 } }
删除这条记录的时候,
_verison
也会自动加一的。
三、查询
创建了一个索引后,可以通过下面的方式查询(参数
-XGET
)出来
curl -XGET ‘http://localhost:9200/test/users/1?pretty‘ { "_index" : "test", "_type" : "users", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "user" : "test", "post_date" : "2009-11-15T14:12:12", "message" : "Elastic Search" } }
执行上面的查询命令,可以等到下面的结果,
exists
表示是否有查询结果,
_source
字段是查询到的记录。
查询的时候,可以将
_type
设置成为
_all
,ES就会返回在
_index
下所有type中,第一个匹配
_id
的记录,还可以通过参数对返回结果继续控制,
用fields选取返回的字段,用pretty控制返回的json格式是否更阅读友好
curl -XGET ‘http://localhost:9200/test/users/1?fields=message,user&pretty=true‘ { "_index" : "test", "_type" : "users", "_id" : "1", "_version" : 3, "found" : true, "fields" : { "message" : [ "Elastic Search" ], "user" : [ "test" ] } }
format=yaml
可以设置输入格式为YAML
curl -XGET ‘http://localhost:9200/test/users/1?fields=message,user&format=yaml‘ --- _index: "test" _type: "users" _id: "1" _version: 1 found: true fields: message: - "Elastic Search" user: - "test"
当然ES还支持一次查询多组记录,即multi get,在URI中是使用关键字_mget,具体可以参考ES的文档multi get。
四、更新
ES同样支持更新,但是更新的方式是通过一个提供的脚本进行的。
ES的做法是,通过index找到相应的存放记录的节点,然后执行脚本,执行完之后,返回新的索引。实际上执行的是一个get和reindex的过程,在这个过程中,通过versioning来控制没有其它的更新操作(这个功能是0.19后可用的)。具体实现的原理应该和elasticsearch Versioning相关。
get,reindex的含义是,ES先取出这条记录,然后根据新数据生成新记录,然后在把新记录放回到ES中(并不会覆盖老的记录)。
首先创建一条记录
curl -XPUTlocalhost:9200/test/type1/1 -d‘{
"counter" : 1,
"tags" : ["red"]
}‘
将counter的值加4
curl -XPOST ‘localhost:9200/test/type1/1/_update‘ -d‘{
"script" : "ctx._source.counter += count",
"params" : {
"count" : 4
}
}‘
也可以添加一个tag的值
curl -XPOST ‘localhost:9200/test/type1/1/_update‘ -d‘{
"script" : "ctx._source.tags += tag",
"params" : {
"tag" : "blue"
}
}‘
现在还支持upsert功能,即在更新的时候,如果记录没有这个key,则插入这个key,下面是一个例子,如果没有
counter
字段,则插入该字段:
curl -XPOST ‘localhost:9200/test/type1/1/_update‘ -d‘{
"script" : "ctx._source.counter += count",
"params" : {
"count" : 4
},
"upsert" : {
"counter" : 1
}
}‘
关于update还有其它很多功能,可以参考ES的API update
五、搜索
elasticsearch的名字里面有一个search,那么主要功能也是search了。
es的search有两种形式,一是通过URI,二是通过Requst Body。通过URI查询,即将查询的语句放入到请求的url中,例如:
curl -XGET ‘http://localhost:9200/twitter/tweet/_search?q=user:kimchy‘
第二种方式,即在查询的请求中加入一个doc
curl -XGET ‘http://localhost:9200/twitter/tweet/_search‘ -d‘{
"query" : {
"term" : { "user" : "kimchy" }
}
}‘
query body的定义可以查看query DSL 另外两种查询方式都可以带参数,参数的含义参考URI Request和Request Body。
ES的搜索功能是可以跨index和type的,例如下面这几条命令
curl -XGET ‘http://localhost:9200/twitter/_search?q=user:kimchy‘ curl -XGET ‘http://localhost:9200/twitter/tweet,user/_search?q=user:kimchy‘ curl -XGET ‘http://localhost:9200/kimchy,elasticsearch/tweet/_search?q=tag:wow‘ curl -XGET ‘http://localhost:9200/_all/tweet/\_search?q=tag:wow‘ curl -XGET ‘http://localhost:9200/\_search?q=tag:wow‘
第一条是在所有的
这个index下的所有type中查找,第二条是在
tweet,user
这两个type中查找,第三条是在
kimchy,elasticsearch
这两个index的
tweet
这个type中查找,第四条使用了
_all
关键字,是在所有的index的
tweet
的type中查找,第五条更暴力,在所有的index和type中查找。
查找还有其它的很多选项,sort,高亮,选取返回记录的域Fields,还可以对返回的域使用一个脚本进行计算script Fields,或者对返回结果继续统计Facets,Facets的内容比较多,它支持关键词统计,范围内统计,直方图式统计,日期的直方图式统计,过滤,查询,还有记录地理位置距离的统计geo distance。 支持名字过滤Named Filters。 定义搜索类型Search Type 。例如什么Query And Fetch,Query Then Fetch。 索引加速的功能Index Boost,可以让某一个索引的权重大于另外一个。 保持上次检索的环境了结果Scroll。保留每一个命中的score值Explain。 设置命中的min_score。保留版本号Version。
Search的参数很多,我也没有一一看,不过果然是名字里面有个search,对检索的各种场景都有支持。
当然还支持多个查询multi search,例如下面这个例子
cat requests {"index" : "test"} {"query" : {"match_all" : {}}, "from" : 0, "size" : 10} {"index" : "test", "search_type" : "count"} {"query" : {"match_all" : {}}} {} {"query" : {"match_all" : {}}} $ curl -XGET localhost:9200/_msearch --data-binary @requests; echo
六、DSL
1、match
curl -XGET ‘localhost:9200/test/_search?pretty‘ -d‘{ "_source": ["title", "allnum"], "query": { "match": { "title": "地铁跑酷" } } }‘ { "took" : 2, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 6.692047, "hits" : [ { "_index" : "test", "_type" : "external", "_id" : "AVicbl1W9iJMapPz5wea", "_score" : 6.692047, "_source" : { "title" : "地铁跑酷", "allnum" : 104541 } } ] } }
显示指定字段,匹配关键字
结果格式
took
– 搜索用的毫秒
timed_out
– 搜索超时时间
_shards
– 搜索了多少个片段 成功搜索多少个 失败了多少个
hits
– 搜索的返回结果集
hits.total
– 结果的总数
hits.hits
– 实际搜索返回的数组
_score
and
max_score
- ignore these fields for now
一旦es搜索返回给你 该链接就断开了 es并不会想MySQL之类的 一直维护一个连接
更多限制条件的搜素
curl -XGET ‘localhost:9200/test/_search?pretty‘ -d‘{ "from": 0, "size": 1, "_source": ["title", "allnum"], "query": { "match": { "title": "地铁跑酷" } }, "sort": { "allnum": { "order": "desc" }} }‘
2、使用should
curl -XGET ‘localhost:9200/test/_search?pretty‘ -d‘{ "from": 0, "size": 2, "_source": ["title", "allnum"], "query": { "bool": { "should": [ { "match": { "title": "地铁跑酷" } }, { "match": { "title": "星猫跑酷" } } ] } }, "sort": { "allnum": { "order": "desc" }} }‘
3、使用must/must not
curl -XGET ‘localhost:9200/test/_search?pretty‘ -d‘{ "from": 0, "size": 2, "_source": ["title", "allnum"], "query": { "bool": { "must": [ { "match": { "title": "地铁跑酷" } }, { "match": { "title": "星猫跑酷" } } ] } }, "sort": { "allnum": { "order": "desc" }} }‘
当然 must /should/must not 可以联合起来使用
4、过滤器
curl -XPOST ‘localhost:9200/test/_search?pretty‘ -d‘{ "query": { "filtered": { "query": { "match_all": {} }, "filter": { "range": { "allumn": { "gte": 20000, "lte": 30000 } } } } } }‘
5、聚合
curl -XPOST ‘localhost:9200/test/_search?pretty‘ -d‘{ "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state" } } } }‘
6、terms 过滤
curl -XPOST ‘localhost:9200/test/_search?pretty‘ -d‘{ "query": { "terms": { "status": [ 304, 302 ] } } }
7、range 过滤
curl -XPOST ‘localhost:9200/test/_search?pretty‘ -d‘{ "query": { "range": { "allnum": { "gt": 1 } } } }
范围操作符包含:
gt :: 大于
gte:: 大于等于
lt :: 小于
lte:: 小于等于
8、exists 和 missing 过滤
exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件
{ "exists": { "field": "title" } }
9、bool 过滤
bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:
must :: 多个查询条件的完全匹配,相当于 and。
must_not :: 多个查询条件的相反匹配,相当于 not。
should :: 至少有一个查询条件匹配, 相当于 or。
这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:
{ "bool": { "must": { "term": { "folder": "inbox" }}, "must_not": { "term": { "tag": "spam" }}, "should": [ { "term": { "starred": true }}, { "term": { "unread": true }} ] } }
七、中文分词
创建索引
curl -XPUThttp://localhost:9200/index
创建映射
curl -XPOSThttp://localhost:9200/index/fulltext/_mapping -d‘ { "fulltext": { "_all": { "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "term_vector": "no", "store": "false" }, "properties": { "content": { "type": "string", "store": "no", "term_vector": "with_positions_offsets", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word", "include_in_all": "true", "boost": 8 } } } }‘
为索引添加一些内容
curl -XPOSThttp://localhost:9200/index/fulltext/1 -d‘ {"content":"美国留给伊拉克的是个烂摊子吗"} ‘ curl -XPOSThttp://localhost:9200/index/fulltext/2 -d‘ {"content":"公安部:各地校车将享最高路权"} ‘ curl -XPOSThttp://localhost:9200/index/fulltext/3 -d‘ {"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"} ‘ curl -XPOSThttp://localhost:9200/index/fulltext/4 -d‘ {"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"} ‘
进行查询
curl -XPOSThttp://localhost:9200/index/fulltext/_search -d‘ { "query" : { "term" : { "content" : "中国" }}, "highlight" : { "pre_tags" : ["<tag1>", "<tag2>"], "post_tags" : ["</tag1>", "</tag2>"], "fields" : { "content" : {} } } } ‘
以上是关于分布式搜索引擎Elasticsearch的查询与过滤的主要内容,如果未能解决你的问题,请参考以下文章