Term Level Query
这里翻译为字段查询,字段查询是查询的文本不会被分词,只有对应的文档精确存在对应的查询文本才会返回。
可以发现,字段查询是指查询文本不会被分词,而不是索引对应的mapping该字段不能分词,即使对应的字段是text属性,只要该文档的字段中存在对应的词元,就会返回。
一般如果没有指定查询文本的分词器,就会使用mapping定义该字段的分词器来分析查询文本,所以一般我们用字段查询都是查询mapping中字段属性为keyword的字段。但是这不意味着match不能搜索keyword定义的字段,也不能说字段查询不能搜索text定义的字段。只要文档中包含查询文本有效的词元都会返回。
索引的mapping
"myindex": {
"aliases": {},
"mappings": {
"mytype": {
"properties": {
"addr": {
"type": "text"
},
"age": {
"type": "integer"
},
"city": {
"type": "keyword"
},
"content": {
"type": "text"
},
"name": {
"type": "keyword"
}
}
}
}
查询1
GET myindex/_search
{
"query": {
"term": {
"addr" : "zhongguo"
}
}
}
查询2
GET myindex/_search
{
"query": {
"match": {
"name" : "mahuateng"
}
}
}
查询3
GET myindex/_search
{
"query": {
"match": {
"addr" : "zhongguo"
}
}
}
都可以返回结果:
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 0.6931472,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
}
]
查询4
GET myindex/_search
{
"query": {
"term": {
"addr" : "zhongguo guangdong guangzhou"
}
}
}
查询5
GET myindex/_search
{
"query": {
"match": {
"name" : "zhangsan lisi"
}
}
}
返回结果:
{
"_index": "myindex",
"_type": "mytype",
"_id": "5",
"_score": 0.2876821,
"_source": {
"name": "zhangsan lisi",
"age": "71",
"addr": "zhongguo guangdong guangzhou",
"city": "guangzhou"
}
}
上例中addr
是text
属性,name
是keyword
属性;
- 第一个查询是字段查询,搜索文本是
zhongguo
,不会被分词(不会因为addr是text属性分词),所以要精确查询文档addr字段中是否存在zhongguo
的文档。 因为文档中addr
的值是zhongguo guangdong shenzhen
,它会形成三个有效词zhongguo
、guangdong
、shenzhen
,所以可以查到到结果。 - 第二个查询是全文搜索,搜索文本是
mahuateng
,它会按照索引定义的name
属性进行分词,因为name
是keyword
属性,所以不会被分词,要精确查询文档那么字段中是mahuateng
的文档。 - 第三个查询是全文搜索,搜索文本是
zhongguo
,它会按照索引定义的addr
属性进行分词,因为addr
是text
属性,所以被分为zhongguo
词元,因为文档中addr
的值是zhongguo guangdong shenzhen
,它会形成三个有效词zhongguo
、guangdong
、shenzhen
,所以可以查到到结果。 - 第四个查询返回为空,因为字段查询,搜索文本是
zhongguo guangdong guangzhou
,不会被分词(不会因为addr是text属性分词),所以要精确查询文档addr
字段中是否存在zhongguo guangdong guangzhou
的文档。 因为文档中addr的值是zhongguo guangdong shenzhen
,它会形成三个有效词zhongguo
、guangdong
、shenzhen
,并没有zhongguo guangdong guangzhou
这个词元,所以没有命中文档。 - 第五个查询可以返回值,是全文搜索,搜索文本是
zhangsan liszi
,它会按照索引定义的name
属性进行分词,因为name
是keyword
属性,所以不会被分词,要精确查询文档那么字段中是zhangsan lisi
的文档。(而不是只要只要含有zhangsan
,lisi
其中一个词元就会返回,这个容易误解)
1、所以我们通常在使用的时候,字段查询通常作用于属性定义为
keyword
的字段。全文搜索通常作用于定义为text
的字段。
2、 字段查询也可以作用于text
的字段。只要文档中精确存在查询文本的对应的词元就会返回
3、全文搜索也可以作用于keyword
字段,只是查询文本不会被分词,要精确配置才会返回。
4、字段查询决定查询文本不能分词,只要文档中精确存在对应的词元就会返回;全文搜索要分词,但是要按照规则分词(一般都是按照文档定义的mapping分词器分词),只要文档中存在分词后任何一个有效词元都会返回。
1.Term Query
单个字段查询:
GET myindex/_search
{
"query": {
"term": {
"name" : "mahuateng"
}
}
}
精确查找name
的反向索引中有mahuateng
的文档。
2.Terms Query
多字段值精确查询
GET myindex/_search
{
"query": {
"terms": {
"name": [
"mahuateng",
"renzhenfei"
]
}
}
}
返回结果:
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 0.9808292,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
},
{
"_index": "myindex",
"_type": "mytype",
"_id": "1",
"_score": 0.2876821,
"_source": {
"name": "renzhenfei",
"age": "71",
"addr": "zhongguo guangdong guangzhou",
"city": "guangzhou"
}
}
]
- terms lookup mechanism:相当于sql中的级联查询(可以跨索引,也可以自己查自己)
支持的参数:
1.index :子查询的索引(与查询相同,可以省略)
2.type:子查询的类型
3.id:子查询的文档的id(其实内部是_id)
4.path:查询的字段
5.routing:可以自定义路由
从上可以发现,只能从id指定,这样的话,其实意义不大。
举个栗子:
定义一个索引
PUT my_other_index
{
"mappings": {
"mytype": {
"properties": {
"attr1" : {
"type": "keyword"
},
"attr2" : {
"properties": {
"attr2_in" :{
"type": "keyword"
}
}
}
}
}
}
}
写入数据:
POST my_other_index/mytype/1
{
"attr1" :[ "1", "2"],
"attr2" :{
"attr2_in" : ["3", "4"]
}
}
展示:
"hits": [
{
"_index": "my_other_index",
"_type": "mytype",
"_id": "1",
"_score": 0.2876821,
"_source": {
"attr1": [
"1",
"2"
],
"attr2": {
"attr2_in": [
"3",
"4"
]
}
}
}
]
现在我们使用级联查询(可以跨索引)
GET myindex/_search
{
"query": {
"terms": {
"_id": {
"index" : "my_other_index",
"type" : "mytype",
"id" : "1",
"path" : "attr2.attr2_in"
}
}
}
}
和
GET myindex/_search
{
"query": {
"terms": {
"_id": {
"index" : "my_other_index",
"type" : "mytype",
"id" : "1",
"path" : "attr1"
}
}
}
}
都可以返回myindex索引中的文档。
返回的结果依次是:
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "4",
"_score": 1,
"_source": {
"name": "zhangqiang",
"age": "32",
"addr": "zhongguo sichuan chengdu say",
"city": "chengdu"
}
},
{
"_index": "myindex",
"_type": "mytype",
"_id": "3",
"_score": 1,
"_source": {
"name": "xiaoyu",
"age": "30",
"addr": "中国安徽亳州",
"city": "shenzhen"
}
}
]
和
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 1,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
},
{
"_index": "myindex",
"_type": "mytype",
"_id": "1",
"_score": 1,
"_source": {
"name": "renzhenfei",
"age": "71",
"addr": "zhongguo guangdong guangzhou",
"city": "guangzhou"
}
}
]
也可以自己查自己
GET myindex/_search
{
"query": {
"terms": {
"age": {
"index" : "myindex",
"type" : "mytype",
"id" : "1",
"path" : "age"
}
}
}
}
含义是查找与文档1相同年龄的人。
3.Range Query
范围查询
- gte:大于等于
- gt:大于
- lte:小于等于
- lt:小于
GET myindex/_search
{
"query": {
"range": {
"age": {
"gt" : 20
}
}
}
}
4.Exists Query
字段存在非空值(空值是:null、[]、 [null] ),""不是空值。
GET myindex/_search
{
"query": {
"exists" :{
"field" : "name"
}
}
}
字段是空值
GET myindex/_search
{
"query": {
"bool": {
"must_not": [
{
"exists" :{
"field" : "name"
}
}
]
}
}
}
5.Prefix Query
前缀查询
GET myindex/_search
{
"query": {
"prefix": {
"name": {
"value": "ma"
}
}
}
}
6.Wildcard Query
通配符查询
- * :匹配任意0个或多个字符
- ?:匹配任意1个字符
GET myindex/_search
{
"query": {
"wildcard": {
"name": {
"value": "ma*hua?*"
}
}
}
}
1.不要使用
*
或者?
开头查询,因为这样会导致特别慢。
2.本身通配符查询效率也不高。
7.Regexp Query
正则表达是查询
GET /_search
{
"query": {
"regexp":{
"name.first": "s.*y"
}
}
}
和通配符?作用不同
通配符?是必须是一个字符
正则是前面的字符出现0次或1次
同样正则表达式可能效率很低
8.Fuzzy Query
模糊查询:和全文搜索参数是一致的。(编辑距离算法)
GET /_search
{
"query": {
"fuzzy" : {
"user" : {
"value" : "ki",
"boost" : 1.0,
"fuzziness" : 2,
"prefix_length" : 0,
"max_expansions": 100
}
}
}
}
9.Ids Query
按照id查询
GET myindex/_search
{
"query": {
"ids": {
"values": "1"
}
}
}
GET myindex/_search
{
"query": {
"ids": {
"values": ["1", "2"]
}
}
}