Elasticsearch中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL(Domain Specified Language) 。
Query DSL是利用 Rest API传递 JSON格式的请求体(RequestBody)数据与 ES进行交互,这种方式的丰富查询语法让 ES检索变得更强大,更简洁。
基本语法:
GET /es_db/_doc/_search {json请求体数据}
#可以简化为下面写法
GET /es_db/_search {json请求体数据}
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl.html
示例数据:
#创建索引,并指定ik分词器
PUT /db_idx4
{
"settings":{
"index":{
"analysis.analyzer.default.type":"ik_max_word"
}
}
}
# 批量创建文档
POST _bulk
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":1}}
{"id":1,"name":"赵子龙","sex":1,"age":18, "address":"三国演义常山赵子龙", "desc":"刘备大将之一"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":2}}
{"id":2,"name":"赵云","sex":1,"age":19, "address":"王者打野刺客赵云", "desc":"王者刺客"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":3}}
{"id":3,"name":"关云长","sex":1,"age":23, "address":"三国演义关云长", "desc":"桃园结义刘备二弟"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":4}}
{"id":4,"name":"关羽","sex":1,"age":23, "address":"王者边路", "desc":"可辅可边"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":5}}
{"id":5,"name":"张益德","sex":1,"age":22, "address":"三国演义张益德", "desc":"桃园结义刘备三弟"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":6}}
{"id":6,"name":"张飞","sex":1,"age":22, "address":"王者辅助", "desc":"王者辅助"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":7}}
{"id":7,"name":"张玄德","sex":1,"age":25, "address":"三国演义张玄德", "desc":"桃园结义刘皇叔"}
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":8}}
{"id":8,"name":"小乔","sex":0,"age":18, "address":"三国演义小乔", "desc":"周瑜之妻"}
使用 match_all,默认只会返回 10条数据。
原因:_search查询默认采用的是分页查询,每页记录数 size的默认值为 10。如果想显示更多数据,指定 size 。
#使用 match_all,默认只会返回 10条数据。
GET /db_idx4/_search
#等同于
GET /db_idx4/_search
{
"query":{
"match_all":{
}
}
}
size 关键字:指定查询结果中返回指定条数。 默认返回值10条。
# 指定 size
GET /db_idx4/_search
{
"query":{
"match_all":{
}
},
"from":1,
"size":3
}
from 关键字:用来指定起始返回位置,和size关键字连用可实现分页效果
GET /db_idx4/_search
{
"query":{
"match_all":{
}
},
"from":2,
"size":200
}
如果 size = 30000,,就会出现异常。

#修改现有某个的索引
PUT /db_idx4/_settings
{
"index.max_result_window":"20000"
}
改动 index.max_result_window参数值的大小,只能解决一时的问题,当索引的数据量持续增长时,在查询全量数据时还是会出现问题。而且会增加 ES服务器内存大结果集消耗完的风险。
最佳实践还是根据异常提示中的采用 scroll api更高效的请求大量数据集。
GET /db_idx4/_search?scroll=1m
{
"query":{
"match_all":{
}
},
"size":2
}

查询结果: 除了返回前2条记录,还返回了一个游标ID值_scroll_id。
# scroll_id 的值就是上一个请求中返回的 _scroll_id 的值
GET /_search/scroll
{
"scroll":"1m",
"scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFmNpTWtscHBSUnVxYmM0ZEtrc1hGMGcAAAAAAAA1ABZlYko0RmdtUlNUT0ItcUo2TDNMbjdn"
}
多次根据 scroll_id游标查询,直到没有数据返回则结束查询。采用游标查询索引全量数据, 更安全高效,限制了单次对内存的消耗。
注意:会让得分失效。
GET /db_idx4/_search
{
"query":{
"match_all":{
}
},
"sort":[
{
"age":"desc"
}
]
}
_source 关键字:是一个数组,在数组中用来指定展示那些字段。
GET /db_idx4/_search
{
"query": {
"match_all": {}
},
"_source": ["name","address"]
}
match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找。
match支持下面几个参数:
#模糊匹配 match 分词后or的效果
GET /db_idx4/_search
{
"query": {
"match": {
"address": "王者打野"
}
}
}
#分词后 and的效果
GET /db_idx4/_search
{
"query": {
"match": {
"address": {
"query": "王者打野",
"operator": "and"
}
}
}
}
当 operator参数设置为 or时,minnum_should_match参数用来控制匹配的分词的最少数量。
#最少匹配打野,刺客两个词
GET /db_idx4/_search
{
"query": {
"match": {
"address": {
"query": "刺客打野",
"operator": "or",
"minimum_should_match": 2
}
}
}
}
multi_match 关键字:可以根据字段类型,决定是否使用分词查询,得分最高的在前面。
GET /db_idx4/_search
{
"query":{
"multi_match": {
"query": "王者打野",
"fields": ["address", "desc"]
}
}
}
注意:字段类型分词,将查询条件分词之后进行查询,如果该字段不分词就会将查询条件作为整体进行查询。
允许我们在单个查询字符串中指定 AND | OR | NOT条件,同时也和 multi_match query 一样,支持多字段搜索。和match类似,但是 match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
注意:查询字段分词就将查询条件分词查询,查询字段不分词将查询条件不分词查询。
#未指定字段查询
GET /db_idx4/_search
{
"query":{
"query_string": {
"query": "赵云 OR 赵子龙"
}
}
}
#指定单个字段查询
GET /db_idx4/_search
{
"query":{
"query_string": {
"default_field": "address",
"query": "赵云 OR 赵子龙"
}
}
}
#指定多个字段查询
GET /db_idx4/_search
{
"query":{
"query_string": {
"fields": ["address","name"],
"query": "赵云 OR 赵子龙 OR 张飞"
}
}
}
类似Query String,但是会忽略错误的语法,同时只支持部分查询语法,不支持AND OR NOT,会当作字符串处理。
支持部分逻辑:
#simple_query_string 默认的operator是OR
GET /db_idx4/_search
{
"query":{
"simple_query_string": {
"query": "王者打野",
"fields": ["address","desc"],
"default_operator": "OR"
}
}
}
GET /db_idx4/_search
{
"query":{
"simple_query_string": {
"query": "王者+打野",
"fields": ["address","desc"]
}
}
}
Term用来使用关键词查询(精确匹配),还可以用来查询没有被进行分词的数据类型。
一般模糊查找的时候,多用 match,而精确查找时可以使用 term。
在 ES中默认使用分词器为标准分词器(Standard Analyzer)标准分词器对于英文单词分词,对于中文单字分词。
在 ES的 Mapping Type 中 keyword,date,integer,long,double,boolean or ip 这些类型不分词,只有 text类型分词。
GET /db_idx4/_search
{
"query": {
"term": {
"address.keyword": "三国演义小乔"
}
}
}
可以通过 Constant Score 将查询转换成一个 Filtering,避免算分,并利用缓存,提高性能。
GET /db_idx4/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"address.keyword": "三国演义小乔"
}
}
}
}
}
对bool,日期,数字,结构化的文本可以利用 term做精确匹配。
GET /db_idx4/_search
{
"query": {
"term": {
"age": {
"value": 18
}
}
}
}
range:范围关键字:
POST /db_idx4/_search
{
"query": {
"range": {
"age": {
"gte": 18,
"lte": 20
}
}
}
}
DELETE /product
POST /product/_bulk
{"index":{"_id":1}}
{"price":100,"date":"2022‐01‐01","productId":"XHDK‐1293"}
{"index":{"_id":2}}
{"price":200,"date":"2022‐02‐01","productId":"KDKE‐5421"}
GET /product/_mapping
GET /product/_search
{
"query": {
"range": {
"date": {
"lte": "now‐2y"
}
}
}
}
ids 关键字 :值为数组类型,用来根据一组id获取多个对应的文档。
GET /db_idx4/_search
{
"query": {
"ids": {
"values": [
1,
2
]
}
}
}
highlight 关键字:可以让符合条件的文档中的关键词高亮。
highlight相关属性:
GET /db_idx4/_search
{
"query": {
"term": {
"address": {
"value": "王者"
}
}
},
"highlight": {
"fields": {
"*": {}
}
}
}
可以在highlight中使用 pre_tags和 post_tags。
GET /db_idx4/_search
{
"query": {
"term": {
"address": {
"value": "王者"
}
}
},
"highlight": {
"post_tags": [
"</span>"
],
"pre_tags": [
"<span style='color:red'>"
],
"fields": {
"*": {}
}
}
}
GET /db_idx4/_search
{
"query": {
"term": {
"address": {
"value": "王者"
}
}
},
"highlight": {
"pre_tags": [
"<font color='red'>"
],
"post_tags": [
"<font/>"
],
"require_field_match": "false",
"fields": {
"address": {},
"desc": {}
}
}
}
更多使用可查看官方文档。
– 求知若饥,虚心若愚。
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果
我目前正在尝试了解RoR。我将两个字符串传递到我的Controller中。一个是随机的十六进制字符串,另一个是电子邮件。该项目用于对数据库进行简单的电子邮件验证。我遇到的问题是当我输入如下内容来测试我的页面时:http://signup.testsite.local/confirm/da2fdbb49cf32c6848b0aba0f80fb78c/bob.villa@gmailcom我在:email的参数散列中得到的全部是'bob'。我在gmail和com之间留下了.,因为那样会导致匹配根本不起作用。我的路由匹配如下:match"confirm/:code/:email"=>"conf
不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a
我正在寻找一种方便实用的方法来将编码值添加到Ruby中的URL查询字符串。目前,我有:require'open-uri'u=URI::HTTP.new("http",nil,"mydomain.example",nil,nil,"/tv",nil,"show="+URI::encode("Rosie&Jim"),nil)pu.to_s#=>"http://mydomain.example/tv?show=Rosie%20&%20Jim"这不是我要找的,因为我需要得到“http://mydomain.example/tv?show=Rosie%20%26%20Jim”,这样show=值就