Elasticsearch入门教程(五):Elasticsearch查询(一)
原文:Elasticsearch入门教程(五):Elasticsearch查询(一)
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
// 准备数据
PUT /shop/goods/1
{
"name": "2017新款女装冬季外套ulzzang棉袄中长款棉衣韩版百搭棉服面包服",
"desc": "",
"price": 268,
"quantity": 9267,
"colors": [
"绿色",
"黑色"
],
"is_discount": true,
"create_date": "2018-01-31 12:10:30",
"ip_addr": "192.168.10.1",
"location": "39.92733,116.39507",
"merchant": {
"id": 999,
"shop_name": "阿依莉旗舰店"
},
"params": [
{
"id": 1,
"label": "型号",
"value": "A30566"
},
{
"id": 2,
"label": "品牌",
"value": "阿依莉"
}
],
"activity": "买一送一"
}
PUT /shop/goods/2
{
"name": "2018春季长袖t恤女加绒加厚圆领宽松套头毛衣女装韩版学生毛线衣",
"price": 108,
"quantity": 268,
"colors": [
"白蓝红",
"红白黑"
],
"is_discount": false,
"create_date": "2017-01-31 12:10:30",
"ip_addr": "192.168.10.1",
"location": "39.92733,116.39507",
"merchant": {
"id": 6666,
"shop_name": "美特斯邦威旗舰店"
},
"params": [
{
"id": 1,
"label": "型号",
"value": "HWT8030"
},
{
"id": 2,
"label": "品牌",
"value": "美特斯邦威"
}
]
}
PUT /account/users/1
{
"username": "xiaoming",
"nickname": "小明的老师",
"age": 6,
"height": 1.68,
"birthday": "2017-01-31",
"hobbies": ["吃", "喝", "嫖", "赌"]
}
PUT /accounts/users/1
{
"username": "teacher",
"nickname": "谁能求姐",
"age": 6,
"height": 1.68,
"birthday": "2017-01-31",
"hobbies": ["批评小明"]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
_search
注意:_search即支持GET也支持POST
GET /_search // 空查询:查询所有索引下的所有文档
GET /{index}/_search // 查询某个索引下的前10条文档
GET /{index}/{type}/_search // 查询某个索引下某个类型的前10条文档
- 1
- 2
- 3
- 4
// 返回结果
took字段表示该操作的耗时(单位为毫秒),
timed_out字段表示是否超时,
_shards:在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个
total:返回记录数,本例是2条。
max_score:最高的匹配程度,本例是1.0。
hits:返回的记录组成的数组。
返回的记录中,每条记录都有一个_score字段,表示匹配的程序,默认是按照这个字段降序排列。
多索引,多类型
GET /{index1},{index2}/_search // 查询多个索引下的文档
GET /{index*}/_search // 索引支持*号通配符
GET /{index*},{index*}/_search
GET /_all/_search // 和GET /_search效果一样,_all:表示所有索引
GET /{index}/{type1},{type2}/_search
- 1
- 2
- 3
- 4
- 5
- 6
- 7
// 示例
GET /_search
GET /shop/_search
GET /shop/goods/_search
POST /shop/goods/_search
GET /shop,account/_search
GET /account*/_search
GET /account*,sho*/_search
GET /_all/_search
GET /shop/goods,products/_search
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
查询字符串
查询字符串:就是在_search上使用GET参数的形式对search进行查询过滤,即将参数追加到路径上,此种方式有局限性,不够灵活
- q: 通过加号+来指定查询中的某个字段必须包含某个值,默认是加号,通过减号-来指定文档中不能包含某个值,使用冒号将字段和值分隔,如 q=last_name:Smith,类似于关系型数据库中的where中的 like和not like 操作,
- _source:用于指定要查询的字段,默认会返回文档中的所有字段,多个字段用逗号分隔
- size: 设置search是返回的消息的条数,默认是10
- from: 设置跳过的页数,默认是0,可以通过from和size来达到分页的目的
- sort: 指定对那个字段进行什么排序,默认是按照相关性评分来降续排序的_score, 例如sort=date:desc&sort=_score
- version: 版本号,用于更新和删除操作,当文档的版本等于指定的版本号时才能正常执行,否则会返回409 版本冲突 (乐观并发控制)
- ersion_type=external 用于创建、修改、删除操作 外部版本号:当使用外部版本号是es会检查版本号是否比_version值小,如果小的话就正常执行,并将_version的值更改为外部的版本号, 例如version=5&version_type=external
- timeout=10ms 指定超时时间,默认单位是毫秒ms,也可以指定秒s,例如1s
- retry_on_conflict=n 参数来设置自动完成这项请求的次数,它的默认值是0,失败前重新尝试n次
- scroll=1m 游标查询,保持游标查询窗口一分钟
// q好像对中文查询不出啦???可以通过其他方式进行查询
// 查询字段包含的字符串q=filed:value, 类似于SQL中的where last_name like '%Smith%'
GET /{index}/{type}/_search?q=last_name:Smith
// 加号+:表示必须存在,每部分都是包含的意思, 类似于SQL中的where fist_name like '%join%' and like '%Smith%'
// + 前缀表示必须与查询条件匹配。类似地, - 前缀表示一定不与查询条件匹配。
// 没有 + 或者 - 的所有其他条件都是可选的,类似于or——匹配的越多,文档就越相关
GET /{index}/{type}/_search?q=fist_name:join+last_name:Smith'
// -号代表不包含, 类似于SQL中的 where name not like '%join%'
GET /{index}/{type}/_search?q=-name:join
// name包含join但tweet不包含jmary的, 类似于SQL中的 where name like '%join%' and tweet not like '%mary%'
GET /{index}/{type}/_search?q=name:join+-tweet:mary
// 查询所有索引所有类型所有字段中包含mary关键字的文档, _all:可以代表所有索引或者所有类型或者所有字段,
// 每个文档都有一个隐形的_all字段,它的数据类型是文本型,它的值是以空格的形式将文档的所有字段的值拼接起来, 例如一个文档有三个值 age: 15, name:zhangsan, birthday:2018-09-15, 那么_all的值为“15 zhangsan 2018-09-15”
// _all会被分词,如果字段中包含日期,例如2018-09-15会被分析成2018,09, 15 三个词条(token)
GET /{index}/{type}/_search?q=_all:mary
// 如果不指定字段则默认是_all字段, _all字段是String类型
GET /{index}/{type}/_search?q=mary
POST /shop/goods/_search?_source=name,price
POST /shop/goods/_search?timeout=10ms
POST /shop/goods/_search?from=0&size=5
POST /shop/goods/_search?sort=create_date:desc&sort=_score
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
查询表达式DSL
使用查询领域特定语言(Query Domain Specific Language) 简称为DSL, 需要使用JSON作为主体,请求体查询
query
- match:模糊匹配,类似于SQL中的like,示例{ “match” : { “field” : “keyword” }},
- match_all:简单的匹配所有文档 {“match_all”: {}}
- match_phrase: 对于短语或者段落进行精确匹配
- match_phrase_prefix
- multi_match: 在多个字段上反复执行相同查询
- bool 用于表示复合语句,用于组合多个查询语句;将多查询组合成单一查询
- must 必须匹配这些条件才能被包含进来,表示并且的关系
- must_not 必须不 匹配这些条件才能被包含进来
- should 如果满足这些语句中的任意语句,将增加 _score ,否则无任何影响。它们主要用于修正每个文档的相关性得分。
- minimum_should_match:控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比, 如 minimum_should_match: 2 或者 “minimum_should_match”: “75%”
- filter 必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档, filter只是简单的数据过滤,并不影响评分,因filter不计算评分,所以性能更好,请尽可能多的使用过滤式查询
- exists 查找包含某个字段的文档
- range 范围,可以使用大于gt、大于等于gte、小于lt、小于等于lte作为查询条件,可用于数字、日期类型、字符串
- term 精确查询,对数值,日期,布尔,not_analyzed确切值字符串
- terms 指定多个匹配值,如果字段包含其中的任何一个,都会返回文档,类似于SQL中的IN 操作
- constant_score: 恒定分数,它将一个不变的常量评分应用于所有匹配的文档
- wildcard: 通配符, ? 匹配任意字符, * 匹配 0 或多个字符
- fuzzy: 模糊查询
- dis_max:分离 最大化查询(Disjunction Max Query)
- nested : 用于操作嵌套类型
highlight 高亮,匹配的结果会被 HTML字符包裹住,需要指定匹配的字段
- aggs 聚合操作,类似SQL中的Group By
- sort 排序
- from 偏移量,类似于SQL中limit中的offset
- size 返回数量,类似于SQL中limit中的count,可以通过from,size来达到分页的效果
// 使用DSL查询肯能条件很多,比较复杂,可以通过使用验证API来检查一个查询是否有效
GET /{index}/{type}/_validate/query?explain
{
"query": {
...
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
数据准备
DELETE /shop/goods/_all 删除所有文档
match 匹配查询
全文检索方式查询,类似于关系型数据库中的like操作,使用match时需要指定对那个字段进行全文检索,以及对应的关键字, 关键字可以指定一个也可以指定多个,指定多个时表示或者的关系 类似于SQL中的or的功能。语法:
{ "match" : { "field" : "keyword" }}
类似于SQL中的where filed like ‘%keyword%’
{ "match" : { "field" : "keyword1 keyword2" }}
类似于SQL中的where field like ‘%keyword1%’ or field like ‘%keyword2%’
示例:
// 查询name中包含“女装”的文档
GET /shop/goods/_search
{
"query": {
"match": {
"name": "女装"
}
}
}
// 多词查询 :使用空格隔离多个单词
// 查询name中包含“外套” 或者or 包含 “休闲” 的文档,多个关键字使用空格分隔,如果不指定operator默认是or
GET /shop/goods/_search
{
"query": {
"match": {
"name": "外套 休闲"
}
}
}
// "name": "外套 休闲" or 等价于bool中的should
GET /shop/goods/_search
{
"query": {
"bool": {
"should": [
"match": { "name": "外套" },
"match": { "name": "休闲" },
]
}
}
}
// 查询name中包含“外套” 并且 包含 “休闲” 的文档,多个关键字使用空格分隔
GET /shop/goods/_search
{
"query": {
"match": {
"name": "外套 休闲",
"operator": "and"
}
}
}
// "name": "外套 休闲" and 等价于bool中的must
GET /shop/goods/_search
{
"query": {
"bool": {
"must": [
"match": { "name": "外套" },
"match": { "name": "休闲" },
]
}
}
}
// 多词查询中使用or只需要满足一个即可,要求太低,使用and又必须所有词项都必须满足,要求又太高,
// 使用minimum_should_match折中一下,最小匹配:可以指定一个百分比,
// 例如指定4个词项,一个是词项是25%,设置成50%就是至少要满足2个词项
GET /shop/goods/_search
{
"query": {
"match": {
"name": {
"query": "春季 长袖 圆领 学生",
"minimum_should_match": "50%"
}
}
}
}
// 效果和上面一样,等价的
GET /shop/goods/_search
{
"query" : {
"bool": {
"filter": {
"bool" : {
"should" : [
{ "term" : {"name" : "春季"}},
{ "term" : {"name" : "长袖"}},
{ "term" : {"name" : "圆领"}},
{ "term" : {"name" : "学生"}}
],
"minimum_should_match": 2
}
}
}
}
}
// 查询日期
GET /shop/goods/_search
{
"query": {
"match": {
"create_date": "2018-01-31"
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
match一般用于用引号括起来的值,如文本,日期,如果将match用于布尔或者数字等数据类型就变成精确匹配了,而不是全文检索或者模糊匹配了
如果在一个精确值的字段上使用match,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:
match_all
简单的匹配所有文档
GET /shop/goods/_search
{
"query": {
"match_all": {}
}
}
// 上面简写成这样,效果是一样的
GET /shop/goods/_search
{}
// 同样也可以去掉{},更加简洁
GET /shop/goods/_search
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
match_phrase
对于短语或者段落进行精确匹配,
// match如果对一小段文本进行查询,match首先对字段值进行分词,然后对分词进行匹配,相当于SQL中的name like '%女装%' or name like '%冬季%' or name like '%外套%'
GET /shop/goods/_search
{
"query": {
"match": {
"name": "女装冬季外套"
}
}
}
GET /shop/goods/_search
{
"query": {
"match_phrase": {
"name": "女装冬季外套"
}
}
}
// slop:让相对词序位置不那么严格
// 注意上面使用的是“女装冬季外套”,而现在使用的是“套女装冬季”, slop:允许每个词放宽的间隔
// 尽管词语的顺序不正确,查询仍然能匹配,因为我们为它设置了足够高的slop值使匹配时的词序有更大的灵活性。
GET /shop/goods/_search
{
"query": {
"match_phrase": {
"name": {
"query": "外套女装冬季",
"slop": 10
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
match_phrase_prefix
match_phrase_prefix与match_phrase是一样的,只是它允许在文本的最后一项中使用前缀匹配。
可以用于即时搜索(instant search) 或 输入即搜索(search-as-you-type),例如,如果用户输入 johnnie walker bl ,我们希望在它们完成输入搜索条件前就能得到:Johnnie Walker Black Label 和 Johnnie Walker Blue Label 。
GET /shop/goods/_search
{
"query": {
"match_phrase_prefix": {
"name": "女装冬季外套"
}
}
}
// slop:让相对词序位置不那么严格
// 注意上面使用的是“女装冬季外套”,而现在使用的是“套女装冬季”, slop:允许每个词放宽的间隔
// 尽管词语的顺序不正确,查询仍然能匹配,因为我们为它设置了足够高的slop值使匹配时的词序有更大的灵活性。
GET /shop/goods/_search
{
"query": {
"match_phrase_prefix": {
"name": {
"query": "外套女装冬季",
"slop": 10
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
prefix 查询存在严重的资源消耗问题,短语查询的这种方式也同样如此。前缀 a 可能会匹配成千上万的词,这不仅会消耗很多系统资源,而且结果的用处也不大。
索引时输入即搜索
## edge_ngram 自定义过滤器、分词器
PUT /my_index
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}
## 测试分词
GET /my_index/_analyze
{
"analyzer": "autocomplete",
"text": "quick brown"
}
PUT /my_index/_mapping/my_type
{
"my_type": {
"properties": {
"name": {
"type": "text",
"analyzer": "autocomplete", ## 使用自定义的分词器
"search_analyzer": "standard" ## 配置查询对应的分词器
}
}
}
}
POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "name": "Brown foxes" }
{ "index": { "_id": 2 }}
{ "name": "Yellow furballs" }
## 搜索
GET /my_index/my_type/_search
{
"query": {
"match": {
"name": {
"query": "brown fo"
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
multi_match
多个字段上使用相同的值作为查询条件
GET /shop/goods/_search
{
"query": {
"multi_match": {
"query": 268,
"fields": ["price", "quantity"]
}
}
}
// 两者效果相同
GET /shop/goods/_search
{
"query": {
"bool": {
"should": [
{ "term": { "price": { "value": 268 } } },
{ "term": { "quantity": { "value": 268 } } }
]
}
}
}
// 查询字段名称的模糊匹配
// 字段名称可以用模糊匹配的方式给出:任何与模糊模式正则匹配的字段都会被包括在搜索条件中,
例如可以使用以下方式同时匹配 book_title 、 chapter_title 和 section_title (书名、章名、节名)这三个字段:
{
"multi_match": {
"query": "Quick brown fox",
"fields": "*_title"
}
}
// 提升单个字段的权重
// 可以使用 ^ 字符语法为单个字段提升权重,在字段名称的末尾添加 ^boost ,其中 boost 是一个浮点数:
// chapter_title 这个字段的 boost 值为 2 ,而*_title 字段的默认 boost 值为 1
{
"multi_match": {
"query": "Quick brown fox",
"fields": [ "*_title", "chapter_title^2" ] (1)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
constant_score 常量分数
通常当查找一个精确值的时候,我们不希望对查询进行评分计算。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分。
它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助. 这种方式可以用来取代只有 filter 语句的 bool 查询
GET /shop/goods/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"price": 268.00
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
查询置于 filter 语句内不进行评分或相关度的计算,所以所有的结果都会返回一个默认评分 1
prefix 前缀查询
前缀查询:要查询的字段必须没有分词
默认状态下, prefix 查询不做相关度评分计算,它只是将所有匹配的文档返回,并为每条结果赋予评分值 1 。它的行为更像是过滤器而不是查询。 prefix 查询和 prefix 过滤器这两者实际的区别就是过滤器是可以被缓存的,而查询不行。
prefix 查询或过滤对于一些特定的匹配是有效的,但使用方式还是应当注意。当字段中词的集合很小时,可以放心使用,但是它的伸缩性并不好,会对我们的集群带来很多压力。可以使用较长的前缀来限制这种影响,减少需要访问的量。
PUT /my_index
{
"mappings": {
"address": {
"properties": {
"postcode": {
"type": "keyword"
}
}
}
}
}
PUT /my_index/address/1
{ "postcode": "W1V 3DG" }
PUT /my_index/address/2
{ "postcode": "W2F 8HW" }
PUT /my_index/address/3
{ "postcode": "W1F 7HW" }
PUT /my_index/address/4
{ "postcode": "WC1N 1LZ" }
PUT /my_index/address/5
{ "postcode": "SW5 0BE" }
// prefix 查询
GET /my_index/address/_search
{
"query": {
"prefix": {
"postcode": {
"value": "W1"
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
wildcard 和 regexp
与 prefix 前缀查询的特性类似, wildcard 通配符查询也是一种底层基于词的查询,与前缀查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符。
GET /my_index/address/_search
{
"query": {
"wildcard": {
"postcode": "W?F*HW"
}
}
}
// 词必须以 W 开头,紧跟 0 至 9 之间的任何一个数字,然后接一或多个其他字符
GET /my_index/address/_search
{
"query": {
"regexp": {
"postcode": "W[0-9].+"
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
wildcard 和 regexp 查询的工作方式与 prefix 查询完全一样,它们也需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID ,与 prefix 查询的唯一不同是:它们能支持更为复杂的匹配模式。
这也意味着需要同样注意前缀查询存在性能问题,对有很多唯一词的字段执行这些查询可能会消耗非常多的资源,所以要避免使用左通配这样的模式匹配(如: *foo 或 .*foo 这样的正则式)。
数据在索引时的预处理有助于提高前缀匹配的效率,而通配符和正则表达式查询只能在查询时完成,尽管这些查询有其应用场景,但使用仍需谨慎。
prefix 、 wildcard 和 regexp 查询是基于词操作的,如果用它们来查询 analyzed 字段,它们会检查字段里面的每个词,而不是将字段作为整体来处理。
range
用于查询一个区间,一般用于日期和数值,支持 gt、gte、lt、lte, 示例{“range”: { “age”: { “gte”: 20, “lt”:30 }}} 类似于SQL中的 wher age >= 20 and age < 30
GET /shop/goods/_search
{
"query": {
"range": {
"price": {
"gt": 200,
"lte": 500
}
}
}
}
// 日期类型
GET /shop/goods/_search
{
"query": {
"range": {
"create_date": {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-07 00:00:00"
}
}
}
}
// 日期计算:过去一小时
GET /shop/goods/_search
{
"query": {
"range": {
"create_date": {
"gt" : "now-1h"
}
}
}
}
// 日期计算:早于 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零时)
GET /shop/goods/_search
{
"query": {
"range": {
"create_date": {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-01 00:00:00||+1M"
}
}
}
}
// 作用于字符串,性能相对较慢
"range" : {
"title" : {
"gte" : "a",
"lt" : "b"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
term
精确查询:用于精确值匹配,对数值,日期,布尔,not_analyzed确切值字符串, term 查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。
GET /shop/goods/_search
{
"query": {
"term": {
"is_discount": {
"value": true
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
terms
同term查询,但是它允许指定多个匹配值,一般用于数组,如果字段包含其中的任何一个,都会返回文档, 类似于where tag IN (‘value1’, ‘value2’, ‘value3’) 例如:{ “terms”: { “tag”: [ “search”, “full_text”, “nosql” ] }}
GET /shop/goods/_search
{
"query": {
"terms": {
"colors": [
"白蓝红",
"绿色"
]
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
exists
对于相同类型的文档,可能有的文档有某个字段,有的文档没有某个字段,查找包含或者不包含某个字段的文档, 例如: {“exists”: { “field”: “title” }} ,exists 用于查找那些指定字段中是否有值 , 相当于SQL中的IS NOT NULL
null, [] (空数组)和 [null] 所有这些都是等价的,它们无法存于倒排索引中
这些查询经常用于某个字段有值的情况和某个字段缺值的情况。
// 存在某个字段
GET /shop/goods/_search
{
"query": {
"bool": {
"filter": {
"exists": {
"field": "activity"
}
}
}
}
}
// 不存在某个字段
GET /shop/goods/_search
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "activity"
}
}
}
}
}
POST /my_index/posts/_bulk
{ "index": { "_id": "1" }}
{ "tags" : ["search"] }
{ "index": { "_id": "2" }}
{ "tags" : ["search", "open_source"] }
{ "index": { "_id": "3" }}
{ "other_field" : "some data" }
{ "index": { "_id": "4" }}
{ "tags" : null }
{ "index": { "_id": "5" }}
{ "tags" : ["search", null] }
以上文档集合中 tags 字段对应的倒排索引如下:
Token DocIDs
open_source 2
search 1,2,5
1. tags 字段有 1 个值。
2. tags 字段有 2 个值。
3. tags 字段缺失。
4. tags 字段被置为 null 。
5. tags 字段有 1 个值和 1 个 null 。
// 1,2,5 满足条件
GET /my_index/posts/_search
{
"query" : {
"constant_score" : {
"filter" : {
"exists" : { "field" : "tags" }
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
highlight:高亮
匹配的结果会被 HTML字符包裹住,需要指定匹配的字段,”highlight”: {“fields” : {“about” : {}}}
// 高亮: 匹配的结果会被 <em></em> HTML字符包裹住:
curl -i -H 'Content-Type: application/json' -XGET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"pre_tags" : ["<font color='red'>"],
"post_tags" : ["</font>"],
"fields" : {
"about" : {}
}
}
}'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
sort
排序,可以指定一个或者多个字段排序,多个字段使用数组包围,例如:”sort”: { “date”: { “order”: “desc” }}
// 排序,默认情况下是按照相关性评分排序的,最相关的文档排在最前, 默认按_score排序的
// 多级排序,使用date, _score排序
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }},
{ "ids" : { "order": "asc", "mode": "min"}}
]
}
mode:一般用于数组,可以使用min 、 max 、 avg 或是 sum,统计计算数组的指定值排序
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
对字符串排序,sort对字符串排序需要使用到原始值raw,正常情况下文本可能会使用分词器进行分词,而分词器会影响正常的排序,这时可以对同一个字段设置两种类型,对文本设置成text类型,并设置分词器,如果要搜索的话使用text类型字段,然后再为该字段设置一个原始值,该原始值raw字段的fields的数据类型设置为keyword,关键字数据类型是不分词的,不分词的字段可以作为字符串的排序
// fields 多字段:相当于对同一个字段值起不同的名字,赋予这个字段不同的属性(如类型不同,分词器不同等)
PUT /school
{
"mappings": {
"students": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
}
// _score 和 max_score 字段都是 null 。计算 _score 的花销巨大,通常仅用于排序; 我们并不根据相关性排序,所以记录 _score 是没有意义的。如果无论如何你都要计算 _score , 你可以将 track_scores 参数设置为 true
GET /school/students/_search
{
"query": { "match": { "name": "abc" } },
"sort": [ { "name.raw": { "order": "desc" } } ]
}
// 强制计算评分
GET /school/students/_search
{
"track_scores": true,
"query": { "match": { "name": "abc" } },
"sort": [ { "name.raw": { "order": "desc"} } ]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
from
偏移量,类似于SQL中limit中的offset
size
返回数量,类似于SQL中limit中的count,可以通过from,size来达到分页的效果
GET /shop/goods/_search
{
"from": 0,
"size": 20
}
- 1
- 2
- 3
- 4
- 5
游标查询Scroll
使用from, size做分页不能分页太深,太深对性能营销较大,一般获取前1000条数据就算深了,游标查询用于解决深度分页带来的性能问题。
scroll 查询可以用来对Elasticsearch有效地执行大批量的文档查询,而又不用付出深度分页那种代价。游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的 cursor 。游标查询会取某个时间点的快照数据,查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引 ‘视图’ 一样。
深度分页的代价根源是结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。 游标查询用字段_doc来排序。 这个指令让 Elasticsearch 仅仅从还有结果的分片返回下一批结果。启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间,游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。
// 保持游标查询窗口一分钟
// 关键字 _doc 是最有效的排序顺序。
GET /shop/goods/_search?scroll=1m
{
"query": {"match_all": {}},
"sort": ["_doc"],
"size": 1000
}
// 这个查询的返回结果包括一个字段 _scroll_id, 它是一个base64编码的长字符串 。 现在我们能传递字段 _scroll_id 到 _search/scroll
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAMoFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADKRZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAyoWZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAMrFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADLBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn",
"took": 1,
"timed_out": false,
...
}
// 查询接口获取下一批结果:
GET /_search/scroll
{
"scroll": "1m",
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAKbFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAp0WZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAKeFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnxZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn"
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
这个游标查询返回的下一批结果。 尽管我们指定字段 size 的值为1000,我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards.
注意游标查询每次返回一个新字段 _scroll_id。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段 _scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。
bool
布尔查询,这是一个很重要的查询,它可以将其它多种查询封装成一个大的查询,可以使用逻辑操作符(类似于sql中的and、not、or)来组装各个条件, 这是个复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合
用于表示复合语句,用于组合多个查询语句;将多查询组合成单一查询,bool可以放到query下面,也可以嵌套在某个子条件(must、should、must_not)里, 通过嵌套可以构造出更加复杂的过滤条件。
- must: 必须匹配这些条件才能被包含进来。 表示并且的关系,与 SQL中的AND 等价,例如
{"must": [{"match": {"desc": "xxx"}}, {"term": { "quantity": 999}}]},类似于SQL中的where desc like '%xxx%' and quantity = 999
- must_not: 必须不匹配这些条件才能被包含进来, 是对must的取反操作,与SQL中的 != 或者<> 等价, where status != 0
- should 至少有一个语句要匹配, 与 SQL中的 OR 等价,是一个数组,可以有多个值,如果满足这些语句中的任意语句,将增加_score的值, should的作用:or逻辑,如果满足条件评分_score更高
- filter:必须匹配,以过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档, filter只是简单的数据过滤,并不影响评分
- minimum_should_match
bool 查询会为每个文档计算相关度评分 _score ,再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。
must_not 语句不会影响评分;它的作用只是将不相关的文档排除。
所有must语句必须匹配,所有must_not语句都必须不匹配,经测试至少有一个should需要匹配的(在should中写两个条件,每天条件都不满足条件,结果没有任何文档满足),当没有 must 语句的时候,至少有一个 should 语句必须匹配。
GET /shop/goods/_search
{
"query": {
"bool": {
"must": [
{"term": {
"quantity": {
"value": 999
}
}}
],
"must_not": [
{
"term": {
"quantity": {
"value": 9267
}
}
}
],
"should": [
{
"term": {
"is_discount": {
"value": true
}
}
}
],
"filter": {
"range": {
"price": {
"gte": 7777,
"lte": 9999
}
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
// filter中也可以嵌套bool查询,这样内部的bool查询就不参与评分了
// bool中的must must_not should 等会计算评分的,如果不希望计算评分,可将bool放入到filter中,这样既不计算评分又可以使用bool中的逻辑
// 直接使用bool中的filter和将bool再次嵌入到filter中都不计算评分
GET /shop/goods/_search
{
"query": {
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2014-01-01" }}},
{ "range": { "price": { "lte": 29.99 }}}
],
"must_not": [
{ "term": { "category": "ebooks" }}
]
}
}
}
}
}
// 就像我们能控制 match 查询的精度 一样,我们可以通过 minimum_should_match 参数控制需要匹配的
// should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比:
// 这个查询结果会将所有满足以下条件的文档返回:
// title 字段包含 "brown" AND "fox" 、 "brown" AND "dog" 或 "fox" AND "dog" 。
// 如果有文档包含所有三个条件,它会比只包含两个的文档更相关。
GET /my_index/my_type/_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "brown" }},
{ "match": { "title": "fox" }},
{ "match": { "title": "dog" }}
],
"minimum_should_match": 2
}
}
}
// boost 参数被用来提升一个语句的相对权重( boost 值大于 1 )或降低相对权重( boost 值处于 0 到 1 之间),
// 但是这种提升或降低并不是线性的,换句话说,如果一个 boost 值为 2 ,并不能获得两倍的评分 _score 。
// 通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。
// 更高的 boost 值为我们带来更高的评分 _score
GET /_search
{
"query": {
"bool": {
"must": {
"match": {
"content": {
"query": "full text search",
"operator": "and"
}
}
},
"should": [
{ "match": {
"content": {
"query": "Elasticsearch",
"boost": 3
}
}},
{ "match": {
"content": {
"query": "Lucene",
"boost": 2
}
}}
]
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
过滤查询:不需要评分,性能更好,对结果进行缓存
评分查询:需要评分,评分比较费力,不对结果进行缓存
如何选择查询与过滤? 通常的规则是,使用查询(query)语句来进行 全文搜索或者其它任何需要影响相关性得分的搜索。除此以外的情况都使用过滤(filters)。
aggs
聚合操作,类似SQL中的Group By, 支持的聚合类型有avg, min, max, sum, rang 等,也可以对地理位置进行聚合
如果要对一个字段进行聚合,要保证这个字段的fielddata设置为true
PUT /{index}/_mapping/{type}
{
"properties": {
"FILED": {
"type": "text",
"fielddata": true
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
// 统计数组中每个元素出现的次数,中文有问题,现在中文分词是按单个字分词的,估计需要指定对该字段不分词
GET /shop/goods/_search
{
"aggs": {
"xxx": {
"terms": {
"field": "colors",
"size": 10
}
}
}
}
// aggs可以嵌套在aggs中使用
// 嵌套聚合,分级汇总,在聚合中可以进行再聚合,意思是对分组的文档进行其他聚合,而不是对聚合结果进行处理
GET /shop/goods/_search
{
"aggs": {
"xxx": {
"terms": {
"field": "colors",
"size": 10
},
"aggs": {
"yyy": {
"avg": {
"field": "price"
}
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
_mget
multi-get,通过docs数组作为参数指定多个doc来获取多个文档,每个doc可以分别指定索引、类型、id,文档或者api中必须包含index/type/id
// 路径中不包含index、type、id
GET /_mget
{
"docs" : [
{
"_index" : "shop",
"_type" : "goods",
"_id" : 2
},
{
"_index" : "account",
"_type" : "users",
"_id" : 1,
"_source": "nickname"
}
]
}
// 路径中包含index、type, 如果参数中没有指定index、type就使用路径中的,如果参数中明确指定了,就使用参数中的索引和类型
GET /{index}/{type}/_mget
{
"docs" : [
{ "_id" : 2 },
{ "_type" : "account", "_id" : 1 }
]
}
// 路径中指定了索引和类型,通过ids数组指定多个id值
GET /{index}/{type}/_mget'
{
"ids" : [ "2", "1" ]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
_bulk
批量操作:将多个操作封装成一个操作,一次执行多个动作(create,index, update以及delete),并返回每个执行结果.
可以通过_bulk来执行批量插入、批量更新等操作
POST _bulk的请求主体的格式稍微有些不同:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
- 1
- 2
- 3
- 4
- 5
它通过换行符(\n)连接到一起,最后一行也要有\n,每行一定要以换行符(\n)结尾, 包括最后一行 。这些换行符被用作一个标记,可以有效分隔行,这些行不能包含未转义的换行符,因为他们将会对解析造成干扰
- action 必须是以下选项之一:
- create:如果文档不存在,那么就创建它, 相当于 PUT /{index}/{type}/{id}/_create
- index:创建一个新文档或者替换一个现有的文档, 相当于 PUT /{index}/{type}/{id}
- update:部分更新一个文档, 即局部更新文档中的个别字段,相当于 /{index}/{type}/{id}/_update
- delete:删除一个文档,删除操作不需要指定请求体,delete操作没有请求体,它紧接着另一个行为;记得最后一个换行符
- metadata 每个动作需要的参数,json格式的,应该指定被索引、创建、更新或者删除的文档的_index,_type和 _id
每个子请求都是独立执行,因此某个子请求的失败不会对其他子请求的成功与否造成影响。 如果其中任何子请求失败,最顶层的 error 标志被设置为 true ,并且在相应的请求报告出错误明细
这也意味着 bulk 请求不是原子的: 不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求
POST /_bulk
{ "create": { "_index": "shop", "_type": "goods", "_id": 123 }}
{ "name": "My first blog post" }
{ "index": { "_index": "shop", "_type": "goods" }}
{ "name": "My second blog post" }
{ "update": { "_index": "shop", "_type": "goods", "_id": 123, "retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
{ "delete": { "_index": "shop", "_type": "goods", "_id": 1234 }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
我的微信公众号:
Elasticsearch入门教程(五):Elasticsearch查询(一)的更多相关文章
- ElasticSearch入门 第五篇:使用C#查询文档
这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...
- Elasticsearch入门教程(六):Elasticsearch查询(二)
原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- Elasticsearch入门教程(四):Elasticsearch文档CURD
原文:Elasticsearch入门教程(四):Elasticsearch文档CURD 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接: ...
- Elasticsearch入门教程(三):Elasticsearch索引&映射
原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...
- Elasticsearch入门教程(二):Elasticsearch核心概念
原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...
- Elasticsearch入门教程(一):Elasticsearch及插件安装
原文:Elasticsearch入门教程(一):Elasticsearch及插件安装 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...
- 无废话ExtJs 入门教程五[文本框:TextField]
无废话ExtJs 入门教程五[文本框:TextField] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个文本框.如下所示代码区的第42行位置,items: ...
- PySide——Python图形化界面入门教程(五)
PySide——Python图形化界面入门教程(五) ——QListWidget 翻译自:http://pythoncentral.io/pyside-pyqt-tutorial-the-qlistw ...
- RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)
原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
随机推荐
- 6 Java Shell排序
希尔排序是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序. 1.基本思想 将待排序数组按照步长gap进行分组,然后将 ...
- Java工具类-HttpUtil
package com.sh.util; import java.io.IOException; import java.io.UnsupportedEncodingException; import ...
- Note 1 for <Pratical Programming : An Introduction to Computer Science Using Python 3>
Book Imformation : <Pratical Programming : An Introduction to Computer Science Using Python 3> ...
- Druid连接池(无框架)
关于连接池有不少技术可以用,例如c3p0,druid等等,因为druid有监控平台,性能在同类产品中算top0的.所以我采用的事druid连接池. 首先熟悉一个技术,我们要搞明白,为什么要用他, 他能 ...
- pandas之to_datetime时区转换
from datetime import date, datetime, timedelta import time import pandas as pd from pand ...
- ceph-----常用命令
#查看存储池 ceph osd lspools #设置存储池副本数 ceph osd pool set data size 3 #查看存储池具体信息 ceph osd pool ls detail # ...
- js 中文字符串转base64
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- vue文件流转换成pdf预览(pdf.js+iframe)
参考文档:https://www.jianshu.com/p/242525315bf6 PDFJS: https://mozilla.github.io/pdf.js/ 支持获取文件流到客户端 ...
- Dom4j工具j解析XML原理和示例代码
import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; i ...
- -moz-box-shadow
css的box-shadow是用来添加边框阴影效果的. 属性值详解: 1.inset可选值,默认阴影在盒子外使用inset后,阴影在盒子内,即使指定边框或者透明边框,阴影依然存在. 2.<off ...