二.DSL语言高级查询
1.Query DSL概述
**Domain Specific Language **
领域专用语言
Elasticsearch provides a ful1 Query DSL based on JSON to define queries
Elasticsearch提供了基于JSON的DSL来定义查询。
DSL由叶子查询子句和复合查询子句两种子句组成。
2.无查询条件
无查询条件是查询所有,默认是查询所有的,或者使用match_all表示所有
GET /es_db/_doc/_search { "query":{ "match_all":{} } }
返回结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated. { "took" : 12, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 5, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "es_db", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "name" : "张三", "sex" : 1, "age" : 25, "address" : "广州天河公园", "remark" : "java developer" } }, { "_index" : "es_db", "_type" : "_doc", "_id" : "2", "_score" : 1.0, "_source" : { "name" : "李四", "sex" : 1, "age" : 28, "address" : "广州荔湾大厦", "remark" : "java assistant" } }, { "_index" : "es_db", "_type" : "_doc", "_id" : "3", "_score" : 1.0, "_source" : { "name" : "rod", "sex" : 0, "age" : 26, "address" : "广州白云山公园", "remark" : "php developer" } }, { "_index" : "es_db", "_type" : "_doc", "_id" : "4", "_score" : 1.0, "_source" : { "name" : "admin", "sex" : 0, "age" : 22, "address" : "长沙橘子洲头", "remark" : "python assistant" } }, { "_index" : "es_db", "_type" : "_doc", "_id" : "5", "_score" : 1.0, "_source" : { "name" : "小明", "sex" : 0, "age" : 19, "address" : "长沙岳麓山", "remark" : "java architect assistant" } } ] } }
3.有查询条件
3.1 叶子条件查询(单字段查询条件)
3.1.1 模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分
词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹
配的数据,模糊匹配主要通过match等参数来实现
- match : 通过match关键词模糊匹配条件内容
- prefix : 前缀匹配regexp : 通过正则表达式来匹配数据
- match的复杂用法
- match条件还支持以下参数:
- query : 指定匹配的值
- operator : 匹配条件类型
- and : 条件分词后都要匹配
- or : 条件分词后有一个匹配即可(默认)
- minmum_should_match : 指定最小匹配的数量
3.1.2 精确匹配
- term : 单个条件相等
- terms : 单个字段属于某个值数组内的值
- range : 字段属于某个范围内的值
- exists : 某个字段的值是否存在
- ids : 通过ID批量查询
3.2 组合条件查询(多条件查询)
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询
条件
- bool : 各条件之间有and,or或not的关系
- must : 各个条件都必须满足,即各条件是and的
- 关系should : 各个条件有一个满足即可,即各条件
- 是or的关系
- must_not : 不满足所有条件,即各条件是not的
- 关系
- filter : 不计算相关度评分,它不计算_score
- 即相关度评分,效率更高
- constant_score : 不计算相关度评分
- must/filter/shoud/must_not 等的子条件是通
- 过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当
是多个条件时,对应的是一个数组
3.3 连接查询(多文档合并查询)
- 父子文档查询:parent/child
- 嵌套文档查询: nested
3.4 DSL查询语言中存在两种:查询DSL(query DSL)和过滤DSL(filter DSL)
它们两个的区别如下图:
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的
相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个
_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂
的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问
题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用
must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提
高很多性能。一些过滤的情况:
3.5 Query方式查询:案例
根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会
采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
举例:
POST /es_db/_doc/_search { "query": { "term": { "name": "admin" } } } # 等价 SQL: select * from student where name = 'admin'
根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
举例:
POST /es_db/_doc/_search {"from": 0,"size": 2,"query": {"match": {"address": "广州"}}} # 等价 SQL: SQL: select * from user where address like '%广州%' limit 0, 2
多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search { "query":{ "multi_match":{ "query":"张三", "fields":["address","name"] } } } # 等价 SQL: select * from student where name like '%张三%' or address like '%张 三%'
未指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search { "query":{ "query_string":{ "query":"(广州) OR 长沙" } } }
指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search { "query":{ "query_string":{ "query":"admin OR 长沙", "fields":["name","address"] } } }
范围查询注:json请求字符串中部分字段的含义
- range:范围关键字
- gte 大于等于
- lte 小于等于
- gt 大于
- lt 小于
- now 当前时间
POST /es_db/_doc/_search { "query" : { "range" : { "age" : { "gte":25, "lte":28 } } } } # 等价 SQL: select * from user where age between 25 and 28
分页、输出字段、排序综合查询
POST /es_db/_doc/_search { "query" : { "range" : { "age" : { "gte":25, "lte":28 } } }, "from": 0, "size": 2, "_source": ["name", "age", "book"], "sort": {"age":"desc"} }
3.6 Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search { "query" : { "bool" : { "filter" : { "term":{ "age":25 } } } } }
总结:
1. match
match:模糊匹配,需要指定字段名,但是输入会进行分词,比如"hello world"会进行拆分为hello和world,然后匹配,如果字段中包含hello或者 world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。
2. term
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那么会和match查询结果一样,但是如果查询"hello world",结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有"hello world"的字样,而不是查询字段中包含"hello world"的字样。当保存数据"hello world"时,elasticsearch会对字段内容进行分词,"hello world"会被分成hello和world,不存在"hello world",因此这里的查询结果会为空。这也是term查询和match的区别。
3. match_phase
match_phase:会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以"hello world"为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的,hello that word不满足,world hello也不满足条件。
4. query_string
query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
三.文档映射
ElasticSearch 中的 mapping 类似 MySQL 中的 schema 信息,说白了就是表的结构信息。
1.ES中映射可以分为动态映射和静态映射
动态映射:
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),**在文档写入 Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。 **
动态映射规则如下:
静态映射:
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
2 动态映射
2.1 删除原创建的索引
DELETE /es_db # 返回 { "acknowledged" : true }
2.2 创建索引
PUT /es_db # 返回 { "acknowledged" : true, "shards_acknowledged" : true, "index" : "es_db" }
2.3 创建文档(ES根据数据类型, 会自动创建映射)
PUT /es_db/_doc/1 { "name": "Jack", "sex": 1, "age": 25, "book": "java入门至精通", "address": "广州白云机场" } # 返回 { "_index" : "es_db", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
2.4 获取文档映射
GET /es_db/_mapping # 返回 { "es_db" : { "mappings" : { "properties" : { "address" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "age" : { "type" : "long" }, "book" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "sex" : { "type" : "long" } } } } }
3 静态映射
3.1 删除原创建的索引
DELETE /es_db
3.2 创建索引
PUT /es_db
3.3 设置文档映射
PUT /es_db { "mappings":{ "properties":{ "name":{"type":"keyword","index":true,"store":true}, "sex":{"type":"integer","index":true,"store":true}, "age":{"type":"integer","index":true,"store":true}, "book":{"type":"text","index":true,"store":true}, "address":{"type":"text","index":true,"store":true} } } } # 返回 { "error" : { "root_cause" : [ { "type" : "resource_already_exists_exception", "reason" : "index [es_db/HvQwVSaGRdy0gHwI_e49DQ] already exists", "index_uuid" : "HvQwVSaGRdy0gHwI_e49DQ", "index" : "es_db" } ], "type" : "resource_already_exists_exception", "reason" : "index [es_db/HvQwVSaGRdy0gHwI_e49DQ] already exists", "index_uuid" : "HvQwVSaGRdy0gHwI_e49DQ", "index" : "es_db" }, "status" : 400 }
3.4 根据静态映射创建文档
PUT /es_db/_doc/1 { "name": "Jack", "sex": 1, "age": 25, "book": "elasticSearch入门至精通", "address": "广州车陂" } # 返回 { "_index" : "es_db", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
3.5 获取文档映射
GET /es_db/_mapping # 返回 { "es_db" : { "mappings" : { "properties" : { "address" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "age" : { "type" : "long" }, "book" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "sex" : { "type" : "long" } } } } }