--------------------------------------------------------------- 搜索开始--------------------------------------------------------------- ---------------------------------------------------------------
1 es 5.2 以后 type:text 的字段 或默认建立 一个最长 256 个字符的不分词的 fields fields:{“type”:“keyword”,"ignore_above":256}
例子:
put /advanced PUT advanced/_doc/1 { "name":"name2" } GET advanced/_mapping
结果:
{ "advanced": { "mappings": { "_doc": { "properties": { "name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
2 term query 就是不分词。直接匹配。但是只是 查询不分词, 如果 field 是text类型的 ,那么已经被建立了倒排索引,这时候只能使用 keyword 搜索了。
GET advanced/_doc/_search { "query":{ "constant_score": { "filter":{ "term": { "name.keyword": "zhang yu kun" } } } } }
3 上面的 这个 如果在老版本中的解决办法,应该为这个字段建立一个不分词的字段。或者直接让这个字段不分词。或者直接让这个字段的字段设置为 keyword。
4 keyword 类型不分词 。
5 filter 的 数据 会缓存,不会计算相关度分数,而且是在query 之前执行。 filter 查询的 时候 会算出 一个 bitset 里面存着 匹配 用1 来表示 文档id 匹配 ,用 0 表示不匹配。并且 会根据一定规则缓存部分查询的 bitset ,总的来说 最近256 个查询中,查询次数超过一定次数,并且不是出现在太小的 segment (小于1000 或者 3%) 中的会被缓存。
6 terms 多值搜索,相当于in must 相当于 and should 相当于 or( 默认只需要一条的时候)
GET advanced/_doc/_search { "query":{ "constant_score": { "filter":{ "term": { "speciality": "js" } } } } }
GET advanced/_doc/_search { "query":{ "constant_score": { "filter":{ "terms": { "speciality": [ "java", "js" ] } } } } }
备注:如果远字段里面 是 数据,那么只要 有一个值 匹配那么就匹配,如果查询条件是terms 那么就是 相当于in 也就是说 term是 后面数组里面的值是或的关系。in 本来就是或的关系。
7 range query 可以使用 gt gte lt lte 指定范围
GET advanced/_doc/_search { "query":{ "constant_score": { "filter":{ "range": { "age": { "gte": 10, "lte":30 } } } } } }
8 查询的时候可以使用 es 的时间表达式, now-1d 表示当前时间减一天,18-08-27||-30d 表示指定时间减去 30天。 除了 d 以为还有 y M d H m s
9 指定分词以后的 关键字之间的 关系是and ( 默认是 或 )
GET advanced/_doc/_search { "query":{ "match": { "content":{ "query": "zhang yu kun", "operator": "and" } } } }
10 minimum_should_match 默认的 or 的时候自定 匹配 比例( 默认只用匹配到一个)
GET advanced/_doc/_search { "query":{ "match": { "tcontent":{ "query": "zhang yu kun", "operator": "or", "minimum_should_match": "75%" } } } }
备注:如果吧 如果把词 分了以后用 should 匹配 ,然后控制 should 的 最小匹配个数。可以有相同国的效果。据说 而是内部就是分词以后用bool 里面套用 should ,然后使用term query 实现的。
11 指定搜索权重,boost 默认情况下 boost 都是一样的,都是1
GET advanced/_doc/_search { "query":{ "bool": { "should": [ { "match": { "tcontent": { "query": "zhang", "boost":5 } } }, { "match": { "tcontent": "yu" } }, { "match": { "tcontent": "kun" } } ] } } }
12: search_type 里面 query_than_fetch query_and_fetch ,dfs_query_than_fetch ,dfs_query_and_fetch
先查询,返回一个id ,后面再获取doc
查询的的时候就获取到doc
dfs 的头的,在 计算 相关对分数 tf idf 算法的时候 取得 关键字出现总次数 不再是默认的 本shard 而是 全部 shard 。
默认 search_type 是 query_than_fetch
13 遗留问题 为什么 不同 shard 会出现 bound result 的 问题 ?
不同节点 ,如果晒本地 关键字来评分,一个查询会检索 一整 shard ,那么得到的结果 排序后应该总是相等 ,问啥呢?
14 多 field 搜索评分,是 每个字段的 分别搜索的评分加起来然后除以搜索的字段数。得到的平均分。 使用 dis_max 指定分评分为 取 最高的一个。这就是 best field 策略。
GET advanced/_doc/_search { "query":{ "dis_max":{ "queries": [ {"match": { "tcontent": "zhang yu" }}, {"match": { "name": "zhang yu" }} ] } } }
备注: 比如上面例子 在 vcentent 和 name 里面找 zhang yu ,分词后是 zhang 和 yu 如果 一个doc 的 name 和voncent 分别有一个zhang 和 yu ,name 默认分数 是zhang 和 yu 匹配到的分相加除以2.
如果一个 doc 的 name 是zhang yu,vcontent 什么都没有。那么结果是 name 字段的 分 +0 然后除二。这个分可能比 前一个低了。但是我们 dis_max 以后,是取 两个查询分数高的一个作为评分。明显如果是在两个查询字段中找一同样的值。dis_max 比价好 ,如果 是2 个字段找不同的 默认的算法比较好。
备注2: 使用 dis_max 以后 就不是用should 了 ,而是使用 queries了。里面的 查询是 or 的关系 ,并且 是选一个评分最该的最为总评分。
备注3:dis_max 的 dis 我猜是 distribute_max 的意思。分配最大的。
15 使用 tie_breoker 优化 dis_max 查询。( 默认是 各个查询的条件分数的平均值,dis_max 是 取最高值,这个 是取了最高值然后加上别的字段评分的 70% )
GET advanced/_doc/_search { "query":{ "dis_max":{ "queries": [ {"match": { "tcontent": "zhang yu" }}, {"match": { "name": "zhang yu" }} ], "tie_breaker": 0.7 } } }
备注:tie_breoker 是大于 0 小于 1 的数。
16 multi_match 是上面 dis_max 的 另一种写法
GET advanced/_doc/_search { "query":{ "multi_match": { "query": "zhang yu", "fields": [ "name^2" ,"tcontent" ], "tie_breaker": 0.7, "type": "best_fields" } } }
17 上面一个例子的 type best-fields 找分数最高的字段,most-fields 找查到次数最多的。 控制 接近搜索原意的本牌在前面。 老的语法是建立一个 fields 类型是 string 分词器是不分词。
18 ,对于有分词以后有同义词的可以使用 multi_query 在 元字段和 keyword 字段 一起搜,利用
19 cross_fields 的 用法 是不是和 copy_to 类似 的效果,但是呢 如果 "operator" :"and" 的 时候 会让 每个term 必须至少出现在这两个字段中的一个。如果是or 那么 2个联合起来搜索, term 出现任意哥就可以。
说白了 cross_fields 等于 copy_to
20 copy_to 吧 多个字段合并成一个隐藏的字段。(试过了 不是简单的 连接起来),这个好像只能用于搜索,但是 用这个合并出来的字段查不到。感觉没什么用。
PUT advanced2/_mapping/_doc { "properties":{ "f_name":{ "type":"text", "copy_to":"name" }, "l_name":{ "type":"text", "copy_to":"name" } } }
get advanced2/_doc/_search { "query":{ "match": { "name": { "query": "mu tou", "operator":"and" } } } }
21 phrase query 短语匹配 只有包含指定短语的才匹配。短语匹配 默认要求 各个term 都有 ,并且 位置是 便宜量是连续的。可以通过指定slop 指定 最多移动几次。
GET advanced/_doc/_search { "query":{ "match_phrase": { "tcontent": { "query": "zhang kun", "slop":1 } } } }
22 混合使用 match 和 近似 匹配 实现 召回率 和 精确度的 平衡( 在普通的查询上如果有查询到 短语匹配的就加分)
GET advanced/_doc/_search { "query":{ "bool": { "must": [ { "match": { "tcontent": "zhang kun" } } ], "should": [ { "match_phrase": { "tcontent": "zhang kun" } } ] } } }
23 使用 rescore 对查询结果 重打分( 值得是在前面 match 匹配的的同时, 前面 50 个记录使用 短语匹配 ,如果符合那么久共享分数。影响排序,如果不符合 就不共享,并且只有前面50 个这样做,效率高了很多。 ) 是对 22 的优化。
GET advanced/_doc/_search { "query":{ "match": { "tcontent": "zhang kun" } }, "rescore":{ "window_size":50, "query":{ "rescore_query":{ "match_phrase":{ "tcontent": "zhang kun",
"slop":50 } } } } }
24 前缀搜索 ( 这个感觉分词了的 字段部分可以收到,最好搜索 不分词的字段),不计算分数,前缀搜索效率很低
GET /advanced/_doc/_search { "query":{ "prefix": { "tcontent": { "value": "zh" } } } }
25 通配符搜索 * 代表多个字符,? 代表单个字符,性能比较差 需要扫描全部倒排索引。
GET /advanced/_doc/_search { "query":{ "wildcard": { "tcontent": { "value": "z?a*" } } } }
27 正则搜索 效率同样低
GET /advanced/_doc/_search { "query":{ "regexp": { "tcontent": { "value": ".*" } } } }
28 match_phrase_prefix实现search-time搜索推荐 性能依旧差
GET /advanced/_doc/_search { "query":{ "match_phrase_prefix": { "tcontent": { "query": "hello w", "slop":10, "max_expansions": 50 } } } }
29 通过 ngram 实现 index-time 搜索推荐,性能很强
PUT /advanced3 { "settings": { "analysis": { "filter": { "autocomplete_filter":{ "type":"edge_ngram", "min_gram":1, "max_gram":20 } }, "analyzer":{ "autocomplete":{ "type":"custom", "tokenizer":"standard", "filter":[ "lowercase", "autocomplete_filter" ] } } } } }
get advanced3/_analyze { "analyzer":"autocomplete", "text":"zhangyu ku" }
然后最好使用 match_phrase 搜索。
30 bootsting (negative 匹配的 分数乘negative_boost )
GET advanced/_doc/_search { "query":{ "boosting": { "positive": { "match": { "tcontent": "zhang" } }, "negative": { "match": { "tcontent": "yu" } }, "negative_boost": 0.2 } } }
31 常量评分
GET advanced/_doc/_search { "query":{ "constant_score": { "filter": { "match": { "tcontent": "zhang" } }, "boost": 1.2 } } }
32 自定义评分(用某个字段影响评分)
GET advanced/_doc/_search { "query":{ "function_score": { "query": { "prefix": { "tconent": "zhang" } }, "field_value_factor": { "field": "age" } } } }
GET advanced/_doc/_search { "query":{ "function_score": { "query": { "prefix": { "tconent": "zhang" } }, "field_value_factor": { "field": "age", "modifier": "log1p", "factor": 1.2 }, "boost_mode": "multiply" , "max_boost": 1.3 } } }
33 模糊查询(修正查询)
fuzziness 纠正对少个字符,删除,添加或者替换 可以使用-->"fuzziness": "auto"
GET advanced/_doc/_search { "query":{ "fuzzy": { "tconent": { "value": "cheng", "fuzziness": 2 } } } }
--------------------------------------------------------------- 搜索部分结束,ik分词器开始--------------------------------------------------------------- ---------------------------------------------------------------
34 ik的 2 种 分词器 ik_max_word ik_smart .ik_max_word 分的更加细。ik_max_word 只分一次(每个词只出现一次)。 建议 ik_max_word
GET _analyze { "analyzer": "ik_smart", "text": "我是一个中国人" }
35 ik 的安装 下载ik 源码 打包,复制target eleaseselasticsearch-analysis-ik-6.3.2.zip 到 es/plugins/ik 下面 然后重启服务就可以了。如果 ik 没有对应的es 版本。可以直接修改 ik 的 <elasticsearch.version>6.3.2</elasticsearch.version> 到对应的版本级可以了。
PUT /ik_index/_mapping/_doc { "properties":{ "name":{ "type":"text", "analyzer":"ik_max_word" } }
36 ik 的 配置 在 config 目录下面 。IKAnalyzer.cfg.xml 里面可以指定 自定义分词字典,和停用词。 <entry key="ext_dict">目录;木鹿2</entry>
字典分两 大类 ,一是正向字典。停用词。
37 拓展IK的 字典。
官方有个接口 通过http 查询 更新。
修改ik 源码。 ik 的 Dictionary 是一个单例 的类。这个 类里面 DictSegment 向这些 DictSegment 里面填写 我们的自定义字典就可以了
public class Dictionary { /* * 词典单子实例 */ private static Dictionary singleton; private DictSegment _MainDict; private DictSegment _SurnameDict; private DictSegment _QuantifierDict; private DictSegment _SuffixDict; private DictSegment _PrepDict; private DictSegment _StopWords;
singleton._MainDict.fillSegment(word.trim().toCharArray()); 添加词
public void addWords(Collection<String> words) { if (words != null) { for (String word : words) { if (word != null) { // 批量加载词条到主内存词典中 singleton._MainDict.fillSegment(word.trim().toCharArray()); } } } }
我们 可以修改这个项目源码 ,实现监听模式,在 有新词的时候主动告诉我们的 ik 。或者 定时取查询 新的词语。 原理就这样。想怎么该怎么就改了。
--------------------------------------------------------------- ik分词器结束,集合分析开始--------------------------------------------------------------- ---------------------------------------------------------------
38 聚合分析 -分组
GET /ds/_doc/_search { "query":{ "match_all": {} }, "size":0, "aggs":{ "ys":{ "terms": { "field": "color.keyword" } } } }
39 分组 以后分别对 全部数据取平局 和 对分组的数据取平均值
GET /ds/_doc/_search { "query":{ "match_all": {} }, "size":0, "aggs":{ "ys":{ "terms": { "field": "color.keyword" }, "aggs": { "pj": { "avg": { "field": "num" } } } }, "pj":{ "avg": { "field": "num" } } } }
常用的 聚合函数 sum min max value_count
40 直方图分组 ( histogram ),按照 每 interval 里面的 值 一组。
GET /ds/_doc/_search { "query":{ "match_all": {} }, "size":0, "aggs":{ "num":{ "histogram": { "field": "num", "interval": 3 } } } }
41 histogram 还有一个 date_histogram 按照日期间隔分组
extended_bounds 只统计这个日期以内的 数据,
min_doc_count 最少几个会不显示 ,0 表示即便没有一个数据也要显示。
GET /ds/_doc/_search { "query":{ "match_all": {} }, "size":0, "aggs":{ "num":{ "date_histogram": { "field": "create_date", "interval": "day", "format": "yyyy-MM-dd", "min_doc_count": 0, "extended_bounds": { "min": "now/d", "max": "now/d" } } } } }
42 使用 global:{} 获取全部的 文档(可以在聚合的藤椅位置得到全部的结果)
GET /ds/_doc/_search { "query":{ "match": { "color.keyword": "hongse" } }, "size":0, "aggs":{ "sum":{ "sum": { "field": "num" } }, "all_doc":{ "global": {}, "aggs":{ "total_sum":{ "sum": { "field": "num" } } } } } }
43 聚合里面 还是可以带 filter
GET /ds/_doc/_search { "query":{ "match": { "color.keyword": "hongse" } }, "size":0, "aggs":{ "sum":{ "filter": { "range": { "num": { "gte": 5 } } } } } }
44 es 里面 一般都可以用 now-1d 表示时间 类似的 2y 年 , 5 m 分钟 , 等等 。。。。。。。。。。。。
45 聚合分组可以指定 排序字段
GET /ds/_doc/_search { "query":{ "match_all": {} }, "size":0, "aggs":{ "ys":{ "terms": { "field": "color.keyword", "order": { "zs": "desc" } }, "aggs":{ "zs":{ "sum": { "field": "num" } } } } } }
如果有多层下转,那么 排序要在你用的排序字段那层写 排序,并且 使用 层1.层2.字段名 格式。
46 . 三角选着原则
三角 : 精准 实时 大数据 ,只能做到 3 选2
1 精准 + 实时 没有大数据
2 精准 + 大数据 hadoop
3 实时+ 大数据 elasticsearch
47. 近似预估聚合算法 延时 100ms 左右 但是会有0.5% 的误差。精准的算法要慢几十倍。 一般在几秒钟 几分钟 甚至几个小时。
48 cardinality 算法 ,先去重,然后在统计数量
可以使用 precision_threshold 来指定在多大范围内几乎保证100% 的 精确。
49 取一段 数据中 ,指定比例中的最大值。(下面的例子计算的num 是 tp50 tp95 tp99 的值 )
GET ds/_doc/_search { "size":0, "aggs":{ "per":{ "percentiles": { "field": "num", "percents": [ 50, 95, 99 ] } }, "ave":{ "avg": { "field": "per" } } } }
备注: tp50 表示 百分之50 的数据的值都小于指定的值 。同理 tp95 百分之95 的 数据的值都小于 tp95 的值。
上面的算法,大概是 在50% 的那个数据前后取平均值,但是发现用 avg 和 min sum max 结果一样。 ?
50 percentile_ranks 计算 一定值一下的的百分比。
GET ds/_doc/_search { "size":0, "aggs":{ "aaa":{ "percentile_ranks": { "field": "num", "values": [ 3, 6 ] } } } }
总结:
percentiles 是取指定百分比附近的值,
percentile_ranks 是取指定值所在的百分比
51 为什么倒排索引聚合 需要检索整个文档,正排索引不需要?
解释:个人认为 搜索的时候,对查询文本分词以后,每一个 term 取 倒排索引里面查询,如果倒排索引是有序的,那么我们只要去指定的地方查询就是了,如果时候通过hash,那么只要查询term 的hash 对应的位置是否有值就够了。所以查询 倒排索引查询是极其快的。但是 如果 使用倒排索引 聚合。比如 通过男女 分组。1W 个文档中有 100 是符合查询条件的。这个100 用来聚合。这时候我们只知道 这 100 个文档和 倒排索引的关系。 大概是这样的关系
男 doc1,doc2
倒排key doc3( fieldName, position),doc7( fieldName, position)
倒排key2 doc99( fieldName, position),doc1000( fieldName, position)
女 doc15( fieldName, position),doc33( fieldName, position)
上面 这种关系可能不是100 条,可能多余也可能少于 ,因为key 可能对应很多 这次查询不 需要的 doc_id ,doc_id 可能前面 可能出现在多个 key 后面。
时候 我们 需要找出性别,然后分组。我们找出对应的 doc_id 集合中 字段名字是 性别,的全部 倒排索引,然后分组。就得到了我们的需要的。显示 在搜索得到一个docids 的后,我们去找这个docids 的 性别字段的 key 的时候需要检索整个倒排缩影的 value 部分 ,去找key ( 通过 docid 和 字段去值里面找)。明显效率不高。这时候我们就需要 可以考虑 直接通过 docid 去找原文。然后通过原文 去分组。这个明显 查找的数据量小很多。毕竟直接通过docid 去找对应 的原文。但是.......,原文在哪里呀? 原文在磁盘里面。慢。所以 doc value 正排索引就产生了。 他是维护 内存里面 ,并且只维护指定指端的 一个 文档缩影。 可硬通过 id 去找到这里面 这个 这份数据 需要加入正排索引的部分。
重点是在 搜索的doc_ids 后去找。这些doc_ids 在 聚合字段值 的过程中 ,必须要去找 这些 doc_ids 的 全部 倒排索引。
52 elastic 内部使用os cache ,建议给jvm 少量内存,给 欧式cache 跟多内存 ,这样可以加减少 gc 和oom 开销。 比如 64 G 内存的服务器,。最大给jvm 16 G ,剩下都给 oscache
53 column 压缩 ,而是会白值相同的用一个标记代替,二不会真是的吧这个值存多份。
54 对于 分词的字段 ,聚合的时候回报错,需要设置 mapping 里面的 fielddata = true 。
不分词的 字段默认是允许聚合的。不分词的字段在 创建 index的 时候默认就为它添加了 doc value。
fielddata = true 那就建立正排索引,也就是doc value。
55 fielddata 是 lazy 加载的,只有 当聚合用到这个字段的时候才加载。而且触发 加载的时候是整个index的这个 field 都会被加载,而不是用到的 少数 doc 的 field。 field 会使用大量内存,需要对内存做一些限制。
可以通过 indeces.fielddata.cache.size:20% 设置,一般建议不要设置,设置类会如果内存不够会清楚内存,然后在使用的时候有反复加载,也会有大量的gc 消耗。
56 查看 fielddata 占用的内存
GET /_stats/fielddata?fields=*
按照node 查询fielddata 占用
GET /_nodes/stats/indices/fielddata?fields=*
按照node 下面的 index 查看
GET /_nodes/stats/indices/fielddata?fields=*&level=indices
57 circuit breaker
使用 fielddata 会占用大量内存,所以很可能oom(内存溢出),可以指定断路器,在内存溢出的时候直接进入断路器(预估内存会溢出就直接失败)。
indices.breaker.fielddata.limit 默认40% fielddata 占用的最大内存
indices.breaker.request.limit 默认 60% 聚合操作需要的最大内存
indices.breaker.total.limit 上面2 个的和 ,默认70%
----------------------------------------------------------------------------------------------------------聚合分析结束,数据建模开始---------------------------------------------------------------------------------------------------------------------------------------------------------
58 elasticsearch的 数据类型 总结
待定: long text keyword string boolean date
59 设置的fielddata的 时候可以同 frequency 来指定那些数据不加载。
"filter":{ "frequency":{ "min": 0.01, "min_segment_size": 500 } }
如果这个字段出现次数小于 1% 那么久不加载,在 segment 里面的 doc 数小于 500 的。这个segment 不加载。
60 设置 fielddata的时候 可以是设置 loading:"eager" ,让 查询是加载 fielddata 变成 建立索引 建立 fielddata 。
如果有大量重复字段 可以使用 loading:"eager_global_ordinals" 全局标号 ,来减少内存消耗( 存的就是编的哈,但是明显如果没有 大量重复 编个号会减低速度)。
61 剁成下钻分组统计的时候 深度优先和广度优先问题。
指定 collect_mode:"breadth_first" 表示广度优先。
depth_first 是默认值 ,深度优先。
GET /ds/_doc { "aggs":{ "a":{ "terms": { "field": "", "size": 10, "collect_mode": "depth_first" } } } }
62 es 数据建模的2 中模式
1 传统三范式的 模式( parent child) 优点,数据没有冗余,缺点 在对大量数据搜索的时候,可能应用程序内join 代价很大
2 菲关系型数据库的 冗余模式 优点:直接存的完整的关系,join 没有额外的资源开销 。 缺点: 数据冗余,占用的存储空间大很多。
3 nested object 优点: 没冗余 ,没有外部join 的 资源占用 。 缺点:父子数据必须存在同一个shard 中。 在mapping 指定的时候,使用_parent.type 指定 父类。相当2 个 type ,一个做父 一个做子。父独立添加 添加子的时候需要指定parent 的 id,存数据的时候 通过 parent id 路由,这样父子数据就在同一个 shard 中 。
63 top_hits 对 聚合分组的数据 取 前面几个
GET /ds/_doc/_search { "size":0, "aggs":{ "fz":{ "terms": { "field": "color.keyword" }, "aggs": { "top5": { "top_hits": { "size": 10, "_source": ["name","color"] } } } } } }
64 : path_hierarchy 分词器这是一个 tokenizer 可以对文件目录拆分。
使用用 ,先定义一个分析器,使用 path_hierarchy 这个分词器。然后对是 文件目录的字段使用这个 自定义的分析器就可以了。
65 analyzer analyze tokenizer 的区别?
analyzer 分析器( 名词),一个 分析器包含了分词器,过滤器
analyze 分析(动词)
tokenizer 分词器(名词)
66 es 的锁
创建文档锁:创建一个指定ID的文档,如果可以创建成功那么久获取到了这个锁。es 保证只有一个线程可以创建成功。这个和redis ,zokeeper 一样。感觉 支持分布式的 工具都是利用 唯一创建 开控制分布式锁的。
修改文档锁: 需要脚本 原理 第一次来创建指定id的一条记录,后来修改的时候 带上这个 doc 指定字段的 值,做对比,如果相同 那么就是上锁的人,可以修改,如果不是 那么久不能修改。 用完锁以后删除这条doc 就释放了锁。
我觉得不是全局和 行级 的关系,而是第一种 无状态 ,不识别 创建者。 第二种 识别。如果用同一个id 那么它们都可以是全局锁,如果用不同id 它们都可以是行级锁。
共享锁: 如果第一次加锁 ,就insert ,如果已经存在,判断是否是 共享锁,如果是就 count +1 ,不是就异常。解锁,每次解锁都count--,当count = 0 的时候删除。
排它锁:向一个文档里面写入一个类型标志排它锁,如果创建成功,那么就获取成功,如果创建失败,就 获取失败。 用的是create 不是 upsert 语法。
加了排它 锁不能再加任何锁,加了共享锁还可以加共享锁。 一般用 排它锁写,共享锁读。
67 object 类型 在 存的时候做了一个合并操作 ,有些时候我们需要 指定 内层type = nested 。这样就保留json 的与哪有类型。存成nested 类型以后需要 使用nested 搜索。
不想写了 有点晚了想睡觉了,截个图,偷个懒,score_mode ,如果 查询到多个结果,评分应该怎么评。
68 基于 nested 的 聚合分析( 下面的 结果是查询 博客的 nested 评论中 , 按照月份分组,然后 获取平均 评分) 为什么要在 正常的集合前面 加一层聚合并且 指定了 nested。path = comments,吧这个诞辰给一个集合的意思吗?
69 。感觉只要在前面的集合拆分成几部分,或者去其中一分部的时候就要使用aggs 。
70 reverse_nested 可以取到前面的数据。( 指的是nested 上层数据) 下面是 查询博客里面的评论中,按照年龄分组,然后在按照 tags 分组(分析这个年龄段发帖 的 tags)
71 buck 批处理的时候,使用 定义部分 使用_开头的感觉都是 ? 前面的 id type index 之类的,? 后面的参数 直接写 。不需要加_
72 parent child 数据模型的 查询父,带上子的条件筛选
查询 子生日在一定范围的父
查询 有 2 个 儿子 以上的 父。
查询子,带上父类的筛选条件
聚合统计:使用一层聚合取子, 使用 children.type 指定子。
查询的时候query type 使用 has_child has_parent ,指定内层 查询条件用的 子 或者父。
聚合的时候使用 aggs + children 取出子集合。
73 可以查询父带出子吗?
74 三种 父子关系。
指的注意的一点:因为父子数据需要在同一个shard 里面 所以 第三次只指定 parent id 是不够的 。因为 它是不能用这个 parent id路由,它应该通过最上层的 parent id路由 。这时候 我们直接指定路由id ( routing )
查询的时候 取2层 has_child
-----------------------------------------------------------------------------------------------------数据建模部分结束,实用部分开始-----------------------------------------------------------------------------------------------------------------
75 term vectors 一些描述 term 的 位置 偏移 负载,term 频率 字段评率 等的数据
termvactors 可以出现在 index-time 或者 query-time. 查看语法都一样
GET /ds/_doc/34D9k2UBfN_9dQLLdk-B/_termvectors ,如果没有在index-time 生成 ,那么 查看的时候是也会生成
查询语法:
GET /ds/_doc/34D9k2UBfN_9dQLLdk-B/_termvectors { "fields":["name"], "offsets":true, "payloads":true, "positions":true, "term_statistics":true, "field_statistics":true }
添加语法:
PUT /ds1/_mapping/_doc { "properties":{ "name":{ "type":"text", "term_vector":"with_positions_offsets_payloads" } } }
可以不指定 id 。然后用 doc 指定不存在的一份文档加入统计
GET /ds/_doc/_termvectors { "doc":{ "name": "电视1", "color": "hongse", "num": 1 }, "fields":["name"], "offsets":true, "payloads":true, "positions":true, "term_statistics":true, "field_statistics":true }
可以过滤部分数据:
76 _mtermvectors 批量查询 termvectors
可以吧id type 指定到前面
指定 doc:
77 搜索的高亮 显示( 值得 一提 的是 highlight 部分出现的 必须是 搜索 条件里面出现过的,不然的话就无法 高亮)
备注:高亮就是在搜索的的结果 term 部分加上 <em>term</em> html 里面会显示成红色。
78 三种高亮的
第一: plain highlight 默认
第二: posting highlight ( 在设置mapping 的时候 设置 字段的 index_optionsoffsets)
性能比 plain 高。
对磁盘消耗比较少
可以高亮句子。
第三: fast vector highlight 如果打开了 term_vector 默认就使用的这种高亮。
在在filed 特别巨大的时候( > 1M ),这个性能最高。
强制指定 使用哪种 highlight
指定使用 高亮标签:
高亮设置: fragment 如果文本太长就分成多个片,number_of_fragment 显示多少片
79 搜索模板化 search template
tojos语法:lnline 后面是一整行json 字符串, 把 {{#toJson}}变量{{/toJson}} 之间的部分 设置为下面的 变量后面的 json 对象。 和和上面的区别在于上面是一个简单的 参数值,下面的是一个 json 对象, 感觉最主要的还是后面inline是 json string 。
join 语法: 感觉就是取数组专用的。吧下面的 param是里面的 数组 fangdao 上面 并用 空格隔开和 title="博客 网站" 等价。
指定默认值: ^end 如果没有就定义这个 end 变量。使用中间的默认值 {{^end}}20{{/end}} 如果 后面参数有end那么久用参数,如果后面的参数没有指定 end 那么就用 20 。
条件判断: {{#条件key}} 执行内容 {{/条件key}} 如果指定了条件key。那么中间才会被执行
文件内容
查询语句,前面讲的 几个语法 inline 部分都可以放到 脚本文件里面,然后使用 file 指定 文件,带上参数。
80 suggest 自动完整。 给一个字段指定 fileds.type="completion" 这个es 自动维护 类型 ,不是正排索引也不是倒排索引,不是 前缀搜索。纯内存 速度极快。
定于语法:
查询语法: 查询就不是query 而是 sugest ,并且指定前缀,和 completion.filed=字段.fieldsName
81 模板动态映射
备注:匹配到 long 就是用 下面的 interge 的 mapping ,如果 匹配到 string 就使用 后 mapping的 映射 ,并且 指定 忽略的长度 和不分词的 fileds 。
备注: 后面的 match long_* 表示 long 开头的。 *_text 匹配 _text 结尾的。 unmatch 表示不能 是这个格式。
82. 坐标搜索。 geo_point
PUT /geo PUT /geo/_mapping/_doc { "properties":{ "location":{ "type":"geo_point" } } }
对象格式添加:
put /geo/_doc/1 { "location":{ "lat":40.1, "lon":50 } }
字符串格式添加:
put /geo/_doc/2 { "location":"33.33,44.44" }
数组格式:
put /geo/_doc/2 { "location":[1.55,33.67] }
矩形 左上 和右下 内的 点 查询 (坐标无效,随便写的) bounding_box
GET /geo/_doc/_search { "query":{ "geo_bounding_box":{ "location":{ "top_left":{ "lat":0, "lon":0 }, "bottom_right":{ "lat":0, "lon":0 } } } } }
多点搜索:( 多点组成 的 不规则图形内的点 ) geo_golygon
GET /geo/_doc/_search { "query":{ "geo_polygon":{ "location":{ "points":[ { "lat":0, "lon":0 }, { "lat":0, "lon":0 }, { "lat":0, "lon":0 } ] } } } }
多少距离以内(就是一个圆形): geo_distance
GET /geo/_doc/_search { "query":{ "geo_distance":{ "distance":"200km", "location":{ "lat":40, "lon":-70 } } } }
多段距离统计:坐标统计(下面是统计 几个范围内 ,有几个酒店)
unit: m mi in yd km cm mm 长度单位
stance_type 有三种 : sloppy_arc(默认的),arc(最精准,但是 慢) plane( 最快,不精准 )