正排索引:通过id ,查询content
倒排索引:通过content,查询到符合的 ids
eg:
正排索引就是通过《静夜思》,找到整片文章。
倒排索引通过“明月”,找到《静夜思》 《望月怀古》《关山月》等
索引的基本信息:
GET your_index/_mapping //跟看mysql表字段差不多,可以查看字段的类型type:keyword,text
GET your_index/_alias //查看索引的别名
GET /_cat/health?v //查看集群状态
GET _cat/indices // 查看所有index
GET _cat/shards/your_index //查看指定索引的分片数,每个分片有主(p)副(r)分片
查询索引内容:
-
- GET /you_index/_search
- {
- "query":{
- "match_all": {}
- }
bool bool查询是一个非常强大且常用的复合查询,它允许你组合多个查询条件。bool 查询的核心概念包括以下四种子句:
bool 查询中包含了多个 should 子句,则至少一个 should 子句必须匹配文档。类似于 SQL 中的 OR 操作符。eg:
- GET you_index/_search
- {
- "query": {
- "bool": {
- "must": [
- {
- "bool": {
- "should": [
- {
- "term": {
- "name": {
- "value": "林俊凯",
- "boost": 1
- }
- }
- },
- {
- "term": {
- "zh_name": {
- "value": "林俊凯",
- "boost": 1
- }
- }
- }
- ]
- }
- },
- {
- "bool": {
- "should": [
- {
- "range": {
- "fans_num": {
- "gte": "800"
- }
- }
- },
- {
- "terms": {
- "tag": [
- 1010,
- 1013
- ]
- }
- }
- ]
- }
- }
- ]
- }
- },
- "sort": {
- "_score": {
- "order": "desc"
- },
- "score": {
- "order": "desc"
- }
- }
- }
- "range": {
- "fans_num": {
- "gte": 800,
- "lte":126334
- }
- }
gte:大于等于;lte小于等于
不分词,精准完全匹配查询
- GET your_index_search/_search
- {
- "query": {
- "term": {
- "name": {
- "value": "天空"
- }
- }
- }
- }
不分词,命中数组一个即可,不要求全部命中
- GET your_index_search/_search
- {
- "query": {
- "terms": {
- "tag": [
- "美食",
- "购物"
- ]
- }
-
- }
- }
前缀匹配,不分词 ,精准匹配前半部分
- GET your_index_search/_search
- {
- "query": {
- "prefix": {
- "name_full": {
- "value": "林俊"
- }
- }
-
- }
- }
林俊凯,林俊xxx都会命中
会对query词进行分词
- GET your_index_search/_search
- {
- "query": {
- "bool": {
- "must": [
- {
- "multi_match": {
- "query": "北京景点",
- "fields": [
- "name",
- "name_full",
- "name_lower"
- ],
- "analyzer":"ik",
- "minimum_should_match":"3<80%"
- }
- }
- ]
- }
- }
- }
1. 这里的 "minimum_should_match": "3<80%" 指定了如下规则:
如果分词数量小于或等于 3,则必须匹配所有分词。
如果分词数量大于 3,则至少匹配 80% 的分词。
2. 这里的“analyzer”,是分词器,常见的有ik ik-smart standard mla
- GET _analyze
- {
- "analyzer":"mla",
- "text":"北京景点"
- }
-
- //结果为
- {
- "tokens": [
- {
- "token": "北京",
- "start_offset": 0,
- "end_offset": 2,
- "type": "CN_WORD",
- "position": 0
- },
- {
- "token": "景点",
- "start_offset": 2,
- "end_offset": 4,
- "type": "CN_WORD",
- "position": 1
- }
- ]
- }
3.多个字段上查找,best_fields 表示从所有指定的字段中选择匹配度最高的字段来计算得分.
- {
- "multi_match": {
- "query": "灵岩景区",
- "fields": [
- "title^1.0",
- "content^1.0",
- ],
- "type": "best_fields",
- "operator": "AND",
- "analyzer": "mla",
- "slop": 0,
- "prefix_length": 0,
- "max_expansions": 50,
- "lenient": false,
- "zero_terms_query": "NONE",
- "boost": 1
- }
- }
eg:“北京景点”分词为【北京,景点】,分词项为2,小于3,那么【北京】和【景点】都需要在field中匹配到。multi_match 查询的目的是在多个字段中搜索查询词中的词语,并且匹配规则会跨字段应用,比如 【北京】在name匹配到,【景点】在name_lower配到到,即匹配成功。
注意⚠️:纯英文的按照空格 分词!!!!
会分词,multi_match会涉及多个字段的作用域。match只涉及一个field。 query = 灵岩景区,通过分词为 "灵岩" 和 "景区"。
operator 作用:
如果 "operator": "AND",则文档中必须同时包含 "灵岩" 和 "景区",才会被匹配到。即两个词必须都存在。
如果 "operator": "OR"(默认设置),则文档中只要包含 "灵岩" 或 "景区" 其中一个词,就会被匹配到。这是更宽松的匹配条件。
- $match = new \Elastica\Query\Match();
- $match->setField("name", array(
- "query" => strtolower($params['keyword']),
- "fuzziness" => "AUTO",
- "operator" => "or",
- "analyzer" => "ik_max_word"
- ));
会对query词进行分词(有的人会认为不会分词,❌),match_phrase要求严格,不仅要求,能够匹配到分词后的所有单词,且分词后的单词顺序也要和命中结果中的顺序保持一致。
- GET your_index_search/_search
- {
- "query": {
- "bool": {
- "must": [
- {
- "match_phrase": {
- "name": "孤独的战士"
- }
- }
- ]
- }
- }
- }
name = “孤独的战士” 通过ik_max_word 分词后 【孤独的,孤独,战士】,es中有个name = “孤独星球的战士”是否能被召回呢? 看一下分词:【孤独,星球,战士】。“孤独的”未被匹配到,所以不会被召回。
假如,name = “孤独的战士”的分词为【孤独,战士】,能否召回“孤独星球的战士”呢?可以!通过设置slop,最大间隔数,默认是0。
首先,要看创建索引的时候mapping ,字段的类型。如果是type是keyword,不允许分词。
其次,查看字段类型发现是text,term查询的字段类型只能是keyword
- "keyword_full": {
- "type": "text",
- "fields": {
- "keyword": {
- "type": "keyword"
- }
- }
- },
如果想要查询到想要的文档结果,会有很多因素。首先,用的什么分词器(ik_max_word,ik_smart),分成的tokens决定了匹配度。其次,就是dsl,精准查询就用term ,
最后,写一个例子,多路召回,尽可能多的结果。