elasticsearnch全文检索

全文检索

全文检索最重要的两个方面是

  • 相关度(Relevance)
    根据文档与查询的相关程度对结果集进行排序的能力。相关度可以使用TF/IDF、地理位置相近程度、模糊相似度或其他算法计算。
  • 分析(Analysis)
    将一段文本转换为一组唯一的、标准化了的标记(token),用以(a)创建倒排索引,(b)查询倒排索引。
    注意,一旦提到相关度和分析,指的都是查询(queries)而非过滤器(filters)。
    基于短语(Term-based)的查询
    像term或fuzzy一类的查询是低级查询,没有分析阶段;精确匹配
    全文(Full-text)检索
    match和query_string这样的查询是高级查询,它们会对字段进行分析

一. 匹配查询

match查询的一个主要用途是进行全文搜索
索引一些数据

DELETE /my_index <1>

PUT /my_index
{ "settings": { "number_of_shards": 1 }} <2>

POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "title": "The quick brown fox" }
{ "index": { "_id": 2 }}
{ "title": "The quick brown fox jumps over the lazy dog" }
{ "index": { "_id": 3 }}
{ "title": "The quick brown fox jumps over the quick dog" }
{ "index": { "_id": 4 }}
{ "title": "Brown fox brown dog" }

<1> 删除已经存在的索引(如果索引存在)
<2> 然后,关联失效这一节解释了为什么我们创建该索引的时候只使用一个主分片

单词查询

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}

Elasticsearch通过下面的步骤执行match查询:

  1. 检查field类型
  2. 分析查询字符串
  3. 找到匹配的文档
  4. 为每个文档打分

过程之后得到如下结果:

"hits": [
 {
    "_id":      "1",
    "_score":   0.5, <1>
    "_source": {
       "title": "The quick brown fox"
    }
 },
 {
    "_id":      "3",
    "_score":   0.44194174, <2>
    "_source": {
       "title": "The quick brown fox jumps over the quick dog"
    }
 },
 {
    "_id":      "2",
    "_score":   0.3125, <2>
    "_source": {
       "title": "The quick brown fox jumps over the lazy dog"
    }
 }
]

二. 多词查询

match中可以查询多个关键词

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

修改精度,可以在operator中设置and或or

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {      <1>
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}

minimum_should_match相关的文档,必须匹配的关键词数
可设置为整数或者百分数

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": {
        "query":                "quick brown dog",
        "minimum_should_match": "75%"
      }
    }
  }
}

match查询处理多个词,需要理解bool查询

三. 组合查询

布尔过滤器组合多个用and, or, and not逻辑组成的过滤子句
查询会做的更精细,他们不仅决定一个文档是否要添加到结果集,而且还要计算文档的相关性(relevant)。
像过滤器一样, 布尔查询接受多个用must, must_not, and should的查询子句

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

must和must_not和过滤的作用一样
区别在should,文档不需要同时包含两个关键词,但是同时包含相关性更高
得分计算:must和should子句加起来/must和should子句总数

如果没有must子句,至少匹配一个should子句
minimum_should_match可以控制should子句匹配个数

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 <1>
    }
  }
}

四. match当做bool查询

match查询可以像上面的组合查询一样,当做bool使用;
但是要设置参数operator字段的参数

五. 增加子句

情景:查询full-text search文章,但是涉及到“Elasticsearch”或者“Lucene”的文档更高的权重

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { 
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ 
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}

content字段必须包含full,text,search这三个单词。
如果content字段也包含了“Elasticsearch”或者“Lucene”,则文档会有一个更高的得分。
只给某一个词更高的得分,使用boost控制权重,下面的例子权重不一样,boost在0-1降低得分,>1提高得分

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  (1)
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 (2)
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 (3)
                    }
                }}
            ]
        }
    }
}

六. 分析控制

因为使用到排索引,要保证查询和文档索引时使用的同一个分析器;
因为字段可以独立设置分析器,所以要注意;
添加一个字段到my_index

PUT /my_index/_mapping/my_type
{
    "my_type": {
        "properties": {
            "english_title": {
                "type":     "string",
                "analyzer": "english"
            }
        }
    }
}

使用两种分析api

GET /my_index/_analyze?field=my_type.title   <1>
Foxes

GET /my_index/_analyze?field=my_type.english_title <2>
Foxes

<1> 使用standard分析器的title字段将会返回词foxes。
<2> 使用english分析器的english_title字段将会返回词fox。
如果对fox执行低级别的term查询,english_title字段会匹配而title不会
validate-query API可以返回正确的分析器

GET /my_index/my_type/_validate/query?explain
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title":         "Foxes"}},
                { "match": { "english_title": "Foxes"}}
            ]
        }
    }
}

会返回

(title:foxes english_title:fox)

会为每个字段使用合适的分析器

默认分析器
如果没有指定分析器
在创建索引时顺序

  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

查询时,查找分析器顺序

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

Elasticsearch也支持index_analyzer 和 search_analyzer 参数

  • 加入额外参数之后的顺序
  • 在映射文件中指定字段的index_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的创建索引的默认分析器index_analyzer
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置创建索引的默认分析器default_index
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置创建索引的默认分析器default_index
  • 在节点级别设置默认分析器default
  • standard分析器

查询索引的时候

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的search_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的查询索引的默认分析器analyzer
  • 在索引映射文件中设置查询索引的默认分析器default_search
  • 在索引映射文件中设置默认分析器default_search
  • 在节点级别设置查询索引的默认分析器default_search
  • 在节点级别设置默认分析器default
  • standard 分析器

七. 关联失效

为什么只用一个主分片来创建索引?
处于性能考虑,Elasticsearch不通过索引中所有的文档计算IDF。每个分片会为分片中所有的文档计算一个本地的IDF取而代之。
因为有很好的分布式,所以本地可以代替全局的情况了

posted @ 2016-09-29 20:23  zhangshihai1232  阅读(128)  评论(0)    收藏  举报