Elasticsearch学习笔记

Elasticsearch学习笔记


安装和配置

1.ubuntu 安装 Elasticsearch

1.安装 Java 8 环境

参考:https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-debian-8

  • 安装 Default JRE/JDK
sudo apt-get update
sudo apt-get -y install default-jre
sudo apt-get -y install default-jdk
  • 安装 Oracle JDK
sudo apt-get install software-properties-common
sudo add-apt-repository "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main"
sudo apt-get update
  • Oracle JDK 8
sudo apt-get install oracle-java8-installer
  • 设置 JAVA_HOME 环境变量
sudo update-alternatives --config java

# 复制路径,添加到 /etc/environment 文件中

sudo vim  /etc/environment

# /etc/environment
JAVA_HOME="/usr/lib/jvm/java-8-oracle"

# 重新加载环境变量文件
source /etc/environment

echo $JAVA_HOME
2.安装 Elasticsearch

参考:
https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html
http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html

  • 下载 Elasticsearch Debian 手动安装包并校验(注:6.1.2 可替换为其他任意版本)
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.2.deb
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.2.deb.sha512
shasum -a 512 -c elasticsearch-6.1.2.deb.sha512
  • 安装 Elasticsearch
sudo dpkg -i elasticsearch-6.1.2.deb
  • 安装后的默认路径
安装路径:/usr/share/elasticsearch
配置文件:/etc/elasticsearch
数据存储:/var/lib/elasticsearch
  • 查看启动是否成功
curl localhost:9200
  • 默认情况下,Elasticsearch 只允许本机访问,如果需要远程访问,可以修改 Elastic 安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,然后重新启动 Elasticsearch。
network.host: 0.0.0.0
  • 设为开机自启动
# 判断 init 还是 systemd
ps -p 1

# 若是 init
sudo update-rc.d elasticsearch defaults 95 10

sudo -i service elasticsearch start
sudo -i service elasticsearch stop

# 若是 systemd
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable elasticsearch.service

sudo systemctl start elasticsearch.service
sudo systemctl stop elasticsearch.service
3.中文分词器安装和使用

参考:https://github.com/medcl/elasticsearch-analysis-ik

  • 安装

方法1:从这里下载安装包:https://github.com/medcl/elasticsearch-analysis-ik/releases
/elasticsearch安装路径/plugins/ 下进行解压。

方法2:使用elasticsearch-plugin安装 ( version > v5.5.1 )
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip

安装后重启 Elasticsearch

  • 使用
    1. 创建 Elasticsearch index
curl -XPUT http://localhost:9200/index
  1. 创建 mapping
curl -XPOST http://localhost:9200/index/fulltext/_mapping -d'
{
        "properties": {
            "content": {
                "type": "text",
                "analyzer": "ik_max_word", # 重点在这里,设置分词器 
                "search_analyzer": "ik_max_word" # 重点在这里,设置分词器 
            }
        }

}'

使用

1.重要的查询

match

无论你在任何字段上进行的是全文搜索还是精确查询,match 查询是你可用的标准查询。

如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:

{ "match": { "tweet": "About Search" }}

如果在一个精确值的字段上使用它, 例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}
multi_match

multi_match 查询可以在多个字段上执行相同的 match 查询:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}
range

range 查询找出那些落在指定区间内的数字或者时间:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}

被允许的操作符如下:

gt => 大于
gte => 大于等于
lt => 小于
lte => 小于等于
term

term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

term 查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。

terms

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
exists 和 missing

exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:

{
    "exists":   {
        "field":    "title"
    }
}

这些查询经常用于某个字段有值的情况和某个字段缺值的情况。

2.组合多查询

说明

使用 bool 将多查询组合在一起,成为用户自己想要的布尔查询。它接收以下参数:

must: 文档 必须 匹配这些条件才能被包含进来。

must_not: 文档 必须不 匹配这些条件才能被包含进来。

should: 如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。

filter: 必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

实例一
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}
解释:

查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。
那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。
如果两者都满足,那么它排名将更高。

TIP

如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。
但,如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。

实例二:增加带过滤器的查询编辑

如果我们不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}

通过将 range 查询移到 filter 语句中,我们将它转成不评分的查询,将不再影响文档的相关性排名。由于它现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。

所有查询都可以借鉴这种方式。将查询移到 bool 查询的 filter 语句中,这样它就自动的转成一个不评分的 filter 了。

如果你需要通过多个不同的标准来过滤你的文档,bool 查询本身也可以被用做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:

{
    "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" }}
              ]
          }
        }
    }
}

将 bool 查询包裹在 filter 语句中,我们可以在过滤标准中增加布尔逻辑

constant_score 查询

constant_score 将一个不变的常量评分应用于所有匹配的文档。
它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。

可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。

{
    "constant_score":   {
        "filter": {
            "term": { "category": "ebooks" } 
        }
    }
}

term 查询被放置在 constant_score 中,转成不评分的 filter。这种方式可以用来取代只有 filter 语句的 bool 查询。

3.排序
  • 按照字段的值排序
{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "user_id" : 1 }}
        }
    },
    "sort": { "date": { "order": "desc" }}
}
  • 多级排序
{
    "query" : {
        "bool" : {
            "must":   { "match": { "tweet": "manage text search" }},
            "filter" : { "term" : { "user_id" : 2 }}
        }
    },
    "sort": [
        { "date":   { "order": "desc" }},
        { "_score": { "order": "desc" }}
    ]
}

3.结构化查询

1.精确值查找 参考
  • term 查询数字
    term 查询, 可以用来处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。
    SELECT document
    FROM products
    WHERE price = 20
{
    "query" : {
        "constant_score" : { # 我们用 constant_score 将 term 查询转化成为过滤器
            "filter" : {
                "term" : { 
                    "price" : 20
                }
            }
        }
    }
}
  • term 查询文本
    若要对文本进行精确查找,那么该字段的index必须为not_analyzed
{
    "mappings" : {
        "products" : {
            "properties" : {
                "productID" : {
                    "type" : "string",
                    "index" : "not_analyzed" }
            }
        }
    }
}

SELECT product
FROM products
WHERE productID = “XHDK-A-1293-#fJ3”

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "term" : {
                    "productID" : "XHDK-A-1293-#fJ3" }
            }
        }
    }
}
2.组合过滤器 参考
  • 布尔过滤器
    一个 bool 过滤器由三部分组成:
{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

must 所有的语句都 必须(must) 匹配,与 AND 等价。
must_not 所有的语句都 不能(must not) 匹配,与 NOT 等价。
should 至少有一个语句要匹配,与 OR 等价。

SELECT product
FROM products
WHERE (price = 20 OR productID = “XHDK-A-1293-#fJ3”)
AND (price != 30)

{
   "query" : {
      "filtered" : { #注意,我们仍然需要一个 filtered 查询将所有的东西包起来。
         "filter" : {
            "bool" : {
              "should" : [
                 #在 should 语句块里面的两个 term 过滤器与 bool 过滤器是父子关系,两个 term 条件需要匹配其一。
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} #如果一个产品的价格是 30 ,那么它会自动被排除,因为它处于 must_not 语句里面
              }
           }
         }
      }
   }
}
  • 嵌套布尔过滤器
    SELECT document
    FROM products
    WHERE productID = “KDKE-B-9947-#kL5”
    OR ( productID = “JODL-X-1937-#pV7”
    AND price = 30 )
{
   "query" : {
      "filtered" : {
         "filter" : {
            "bool" : {
              "should" : [ # 因为 term 和 bool 过滤器是兄弟关系,他们都处于外层的布尔逻辑 should 的内部,返回的命中文档至少须匹配其中一个过滤器的条件。 { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, { "bool" : { "must" : [ # 这两个 term 语句作为兄弟关系,同时处于 must 语句之中,所以返回的命中文档要必须都能同时匹配这两个条件。 { "term" : {"productID" : "JODL-X-1937-#pV7"}}, { "term" : {"price" : 30}} ] }} ] }
         }
      }
   }
}
3.查找多个精确值 参考

SELECT document
FROM products
WHERE price in (20,30) # 这条语句仅供参考,并不确切

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "terms" : { # 注意这里是 terms,而非 term
                    "price" : [20, 30]
                }
            }
        }
    }
}
  • 包含,而不是相等
    一定要了解 term 和 terms 是 包含(contains) 操作,而非 等值(equals) (判断)。 如何理解这句话呢?
    如果我们有一个 term(词项)过滤器 { “term” : { “tags” : “search” } } ,它会与以下两个文档 同时 匹配:
{ "tags" : ["search"] }
{ "tags" : ["search", "open_source"] } 

尽管第二个文档包含除 search 以外的其他词,它还是被匹配并作为结果返回。

  • 精确相等
    如果一定期望得到我们前面说的那种行为(即整个字段完全相等),最好的方式是增加并索引另一个字段, 这个字段用以存储该字段包含词项的数量,同样以上面提到的两个文档为例,现在我们包括了一个维护标签数的新字段:
{ "tags" : ["search"], "tag_count" : 1 }
{ "tags" : ["search", "open_source"], "tag_count" : 2 }

一旦增加这个用来索引项 term 数目信息的字段,我们就可以构造一个 constant_score 查询,来确保结果中的文档所包含的词项数量与要求是一致的:

{
    "query": {
        "constant_score" : {
            "filter" : {
                 "bool" : {
                    "must" : [ { "term" : { "tags" : "search" } }, # 查找所有包含 term search 的文档。 { "term" : { "tag_count" : 1 } } # 确保文档只有一个标签。 ] }
            }
        }
    }
}

这个查询现在只会匹配具有单个标签 search 的文档,而不是任意一个包含 search 的文档。

4.范围查找 参考
  • range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:

gt: > 大于(greater than)
lt: < 小于(less than)
gte: >= 大于或等于(greater than or equal to)
lte: <= 小于或等于(less than or equal to)

  • 数字范围
    SELECT document
    FROM products
    WHERE price BETWEEN 20 AND 40
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "range" : {
                    "price" : { "gte" : 20, "lt" : 40 } }
            }
        }
    }
}
  • 日期范围
    range 查询同样可以应用在日期字段上:
"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-07 00:00:00"
    }
}

当使用它处理日期字段时, range 查询支持对 日期计算(date math) 进行操作,比方说,如果我们想查找时间戳在过去一小时内的所有文档:

"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

这个过滤器会一直查找时间戳在过去一个小时内的所有文档,让过滤器作为一个时间 滑动窗口(sliding window) 来过滤文档。

日期计算还可以被应用到某个具体的时间,并非只能是一个像 now 这样的占位符。只要在某个日期后加上一个双管符号 (||) 并紧跟一个日期数学表达式就能做到:

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" # 早于2014年1月1日加1月(2014年2月1日零时)
    }
}

日期计算是 日历相关(calendar aware) 的,所以它不仅知道每月的具体天数,还知道某年的总天数(闰年)等信息。更详细的内容可以参考: 时间格式参考文档 。

5.处理 Null 值 参考
  • 非空查询
    SELECT tags
    FROM posts
    WHERE tags IS NOT NULL
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}

结果:
"hits" : [
    {
      "_id" :     "1",
      "_score" :  1.0,
      "_source" : { "tags" : ["search"] }
    },
    {
      "_id" :     "5",
      "_score" :  1.0,
      "_source" : { "tags" : ["search", null] } # 尽管文档 5null 值,但它仍会被命中返回。字段之所以存在,是因为标签有实际值( search )可以被索引,所以 null 对过滤不会产生任何影响。
    },
    {
      "_id" :     "2",
      "_score" :  1.0,
      "_source" : { "tags" : ["search", "open source"] }
    }
]
  • 缺失查询
    SELECT tags
    FROM posts
    WHERE tags IS NULL
{
    "query" : {
        "constant_score" : {
            "filter": {
                "missing" : { "field" : "tags" }
            }
        }
    }
}

结果:
"hits" : [
    {
      "_id" :     "3",
      "_score" :  1.0,
      "_source" : { "other_field" : "some data" } # tags字段不存在
    },
    {
      "_id" :     "4",
      "_score" :  1.0,
      "_source" : { "tags" : null } # tags 字段为null
    }
]
  • 对象上的存在与缺失
    不仅可以过滤核心类型, exists and missing 查询 还可以处理一个对象的内部字段。以下面文档为例:
{
   "name" : {
      "first" : "John",
      "last" :  "Smith"
   }
}

我们不仅可以检查 name.first 和 name.last 的存在性,也可以检查 name ,不过在 映射 中,如上对象的内部是个扁平的字段与值(field-value)的简单键值结构,类似下面这样:

{
   "name.first" : "John",
   "name.last"  : "Smith"
}

那么我们如何用 existsmissing 查询 name 字段呢? name 字段并不真实存在于倒排索引中。

原因是当我们执行下面这个过滤的时候:

{
    "exists" : { "field" : "name" }
}

实际执行的是:

{
    "bool": {
        "should": [
            { "exists": { "field": "name.first" }},
            { "exists": { "field": "name.last" }}
        ]
    }
}

这也就意味着,如果 first 和 last 都是空,那么 name 这个命名空间才会被认为不存在。

4.全文搜索

1.匹配查询 参考
  • 单个词查询

查找 title 包含 quick 的内容

{
    "query": {
        "match": {
            "title": "QUICK"
        }
    }
}

Elasticsearch 执行上面这个 match 查询的步骤是:

1.检查字段类型 。
标题 title 字段是一个 string 类型( analyzed )已分析的全文字段,这意味着查询字符串本身也应该被分析。

2.分析查询字符串 。
将查询的字符串 QUICK! 传入标准分析器中,输出的结果是单个项 quick 。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询。

3.查找匹配文档 。
用 term 查询在倒排索引中查找 quick 然后获取一组包含该项的文档,本例的结果是文档:1、2 和 3 。

4.为每个文档评分 。
用 term 查询计算每个文档相关度评分 _score ,这是种将 词频(term frequency,即词 quick 在相关文档的 title 字段中出现的频率)和反向文档频率(inverse document frequency,即词 quick 在所有文档的 title 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。参见 相关性的介绍 。

2.多词查询 参考

查找 title 包含 BROWN 或 DOG 的内容

{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}
  • 提高精度
    查找 title 包含 BROWN 和 DOG 的内容
{
    "query": {
        "match": {
            "title": { # match 查询的结构需要做稍许调整才能使用 operator 操作符参数。
                "query": "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}
  • 控制精度(minimum_should_match)
{
    "query": {
        "match": {
            "title": {
                "query": "quick brown dog",
                "minimum_should_match": "75%" # minimum_should_match 最小匹配参数, 这让我们可以指定必须匹配的词项数用来表示一个文档是否相关
            }
        }
    }
}

当给定百分比的时候, minimum_should_match 会做合适的事情:在之前三词项的示例中, 75% 会自动被截断成 66.6% ,即三个里面两个词。无论这个值设置成什么,至少包含一个词项的文档才会被认为是匹配的。

参数 minimum_should_match 的设置非常灵活,可以根据用户输入词项的数目应用不同的规则。完整的信息参考文档 https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-minimum-should-match.html#query-dsl-minimum-should-match

3.组合查询 参考

查找 title 字段包含词项 quick 但不包含 lazy 的任意文档。
关于两个 should 语句:一个文档不必包含 brown 或 dog 这两个词项,但如果一旦包含,我们就认为它们 更相关

{
    "query": {
        "bool": {
            "must":     { "match": { "title": "quick" }},
            "must_not": { "match": { "title": "lazy" }},
            "should": [
                { "match": { "title": "brown" }},
                { "match": { "title": "dog" }}
            ]
        }
    }
}
  • 评分计算

bool 查询会为每个文档计算相关度评分 _score , 再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。
must_not 语句不会影响评分; 它的作用只是将不相关的文档排除。

  • 控制精度

所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,should 语句不是必须匹配。
但是,当没有 must 语句的时候,至少有一个 should 语句必须匹配。

我们也可以通过 minimum_should_match 参数控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比:

{
    "query": {
        "bool": {
            "should": [
                { "match": { "title": "brown" }},
                { "match": { "title": "fox" }},
                { "match": { "title": "dog" }}
            ],
            "minimum_should_match": 2 # 这也可以用百分比表示。
        }
    }
}

这个查询结果会将所有满足以下条件的文档返回: title 字段包含 “brown” AND “fox” 、 “brown” AND “dog” 或 “fox” AND “dog” 。如果有文档包含所有三个条件,它会比只包含两个的文档更相关。

布尔匹配 参考

多词 match 查询只是简单地将生成的 term 查询包裹 在一个 bool 查询中。如果使用默认的 or 操作符,每个 term 查询都被当作 should 语句,这样就要求必须至少匹配一条语句。以下两个查询是等价的:

{
    "query": {
        "match": { "title": "brown fox"}
    }
}
{
    "query": {
        "bool": {
            "should": [
              { "term": { "title": "brown" }},
              { "term": { "title": "fox" }}
            ]
        }
    }
}

如果使用 and 操作符,所有的 term 查询都被当作 must 语句,所以 所有(all) 语句都必须匹配。以下两个查询是等价的:

{
    "query": {
        "match": {
            "title": {
                "query":    "brown fox",
                "operator": "and"
            }
        }
    }
}
{
    "query": {
        "bool": {
            "must": [
              { "term": { "title": "brown" }},
              { "term": { "title": "fox" }}
            ]
        }
    }
}

如果指定参数 minimum_should_match ,它可以通过 bool 查询直接传递,使以下两个查询等价:

{
    "query": {
        "match": {
            "title": {
                "query": "quick brown fox",
                "minimum_should_match": "75%"
            }
        }
    }
}
{
    "query": {
        "bool": {
            "should": [
                { "term": { "title": "brown" }},
                { "term": { "title": "fox" }},
                { "term": { "title": "quick" }}
            ],
            "minimum_should_match": 2 #因为只有三条语句,match 查询的参数 minimum_should_match 值 75% 会被截断成 2 。即三条 should 语句中至少有两条必须匹配。
        }
    }
}
查询语句提升权重 参考
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { # content 字段必须包含 full 、 text 和 search 所有三个词。
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ # 如果 content 字段也包含 Elasticsearch 或 Lucene ,文档会获得更高的评分 _score
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}
{
    "query": {
        "bool": {
            "must": {
                "match": {  # 这些语句使用默认的 boost 值 1 。
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { 
                    "match": {
                        "content": {
                            "query": "Elasticsearch",
                            "boost": 3 # 这条语句更为重要,因为它有最高的 boost 值。
                        }
                    }
                },
                { 
                    "match": {
                        "content": {
                            "query": "Lucene",
                            "boost": 2 # 这条语句比使用默认值的更重要,但它的重要性不及 Elasticsearch 语句。
                        }
                    }
                }
            ]
        }
    }
}

5.多字段搜索

1.多字符串查询 参考
  • 语句的优先级
{
    "query": {
        "bool": {
            "should": [
                {   "match": { "title":  "War and Peace" }},
                {   "match": { "author": "Leo Tolstoy" }},
                { 
                    "bool":  {
                        "should": [# 这里 translator 的权重要小于 title 和 author 的权重 { "match": { "translator": "Constance Garnett" }}, { "match": { "translator": "Louise Maude" }} ] }
                }
            ]
        }
    }
}
{
    "query": {
        "bool": {
            "should": [
                { 
                    "match": { # title 和 author 语句的 boost 值为 2 。
                        "title":  {
                            "query": "War and Peace",
                            "boost": 2
                        }
                    }
                },
                { 
                    "match": { 
                        "author":  {
                            "query": "Leo Tolstoy",
                            "boost": 2
                        }
                    }
                },
                { 
                    "bool":  { # 嵌套 bool 语句默认的 boost 值为 1 。
                        "should": [
                            { "match": { "translator": "Constance Garnett" }},
                            { "match": { "translator": "Louise Maude"      }}
                        ]
                    }
                }
            ]
        }
    }
}
最佳字段 参考
  • dis_max 查询

dis_max 即分离 最大化查询(Disjunction Max Query)
将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回 :

{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Quick pets" }},
                { "match": { "body":  "Quick pets" }}
            ]
        }
    }
}
{
  "hits": [
     {
        "_id": "1",
        "_score": 0.12713557, # 注意两个评分是完全相同的。
        "_source": {
           "title": "Quick brown rabbits",
           "body": "Brown rabbits are commonly seen."
        }
     },
     {
        "_id": "2",
        "_score": 0.12713557, # 注意两个评分是完全相同的。
        "_source": {
           "title": "Keeping pets healthy",
           "body": "My quick brown fox eats rabbits on a regular basis."
        }
     }
   ]
}

我们可能期望同时匹配 title 和 body 字段的文档比只与一个字段匹配的文档的相关度更高,但事实并非如此,因为 dis_max 查询只会简单地使用 单个 最佳匹配语句的评分 _score 作为整体评分。

  • tie_breaker 参数

可以通过指定 tie_breaker 这个参数将其他匹配语句的评分也考虑其中:

{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Quick pets" }},
                { "match": { "body":  "Quick pets" }}
            ],
            "tie_breaker": 0.3
        }
    }
}

结果如下:

{
  "hits": [
     {
        "_id": "2",
        "_score": 0.14757764, 
        "_source": {
           "title": "Keeping pets healthy",
           "body": "My quick brown fox eats rabbits on a regular basis."
        }
     },
     {
        "_id": "1",
        "_score": 0.124275915, 
        "_source": {
           "title": "Quick brown rabbits",
           "body": "Brown rabbits are commonly seen."
        }
     }
   ]
}

tie_breaker 参数提供了一种 dis_max 和 bool 之间的折中选择,它的评分方式如下:

1.获得最佳匹配语句的评分 _score 。
2.将其他匹配语句的评分结果与 tie_breaker 相乘。
3.对以上评分求和并规范化。
4.有了 tie_breaker ,会考虑所有匹配语句,但最佳匹配语句依然占最终结果里的很大一部分。

tie_breaker 可以是 0 到 1 之间的浮点数,其中 0 代表使用 dis_max 最佳匹配语句的普通逻辑, 1 表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,但是合理值应该与零接近(处于 0.1 - 0.4 之间),这样就不会颠覆 dis_max 最佳匹配性质的根本。

multi_match

multi_match 查询为能在多个字段上反复执行相同查询提供了一种便捷方式。

multi_match 多匹配查询的类型有多种,其中的三种恰巧与 了解我们的数据 中介绍的三个场景对应,即: best_fields 、 most_fields 和 cross_fields (最佳字段、多数字段、跨字段)。

默认情况下,查询的类型是 best_fields , 这表示它会为每个字段生成一个 match 查询,然后将它们组合到 dis_max 查询的内部,如下:

{
    "dis_max": {
        "queries":  [
            {
                "match": {
                    "title": {
                        "query": "Quick brown fox",
                        "minimum_should_match": "30%" }
                }
            },
            {
                "match": {
                    "body": {
                        "query": "Quick brown fox",
                        "minimum_should_match": "30%" }
                }
            },
        ],
        "tie_breaker": 0.3
    }
}

上面这个查询用 multi_match 重写成更简洁的形式:

{
    "multi_match": {
        "query":                "Quick brown fox",
        "type":                 "best_fields", # best_fields 类型是默认值,可以不指定。
        "fields":               [ "title", "body" ],
        "tie_breaker":          0.3,
        "minimum_should_match": "30%" # 如 minimum_should_match 或 operator 这样的参数会被传递到生成的 match 查询中。
    }
}
  • 查询字段名称的模糊匹配

字段名称可以用模糊匹配的方式给出:任何与模糊模式正则匹配的字段都会被包括在搜索条件中, 例如可以使用以下方式同时匹配 book_title 、 chapter_title 和 section_title (书名、章名、节名)这三个字段:

{
    "multi_match": {
        "query":  "Quick brown fox",
        "fields": "*_title"
    }
}
  • 提升单个字段的权重

可以使用 ^ 字符语法为单个字段提升权重,在字段名称的末尾添加 ^boost , 其中 boost 是一个浮点数:

{
    "multi_match": {
        "query":  "Quick brown fox",
        "fields": [ "*_title", "chapter_title^2" ] # chapter_title 这个字段的 boost 值为 2 ,而其他两个字段 book_title 和 section_title 字段的默认 boost 值为 1
    }
}

其他

1.中文分词

https://github.com/medcl/elasticsearch-analysis-ik

2.数据同步工具

https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html
https://github.com/siddontang/go-mysql-elasticsearch

3.中文文档

一些博客

https://www.cnblogs.com/xing901022/p/4947436.html

方法小记

批量存入数据
POST /my_store/products/_bulk

{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }

# response
{
    "took": 248,
    "errors": false,
    "items": [
        {
            "index": {
                "_index": "my_store",
                "_type": "products",
                "_id": "1",
                "_version": 1,
                "_shards": {
                    "total": 2,
                    "successful": 1,
                    "failed": 0
                },
                "status": 201
            }
        },
        {
            "index": {
                "_index": "my_store",
                "_type": "products",
                "_id": "2",
                "_version": 1,
                "_shards": {
                    "total": 2,
                    "successful": 1,
                    "failed": 0
                },
                "status": 201
            }
        },
        {
            "index": {
                "_index": "my_store",
                "_type": "products",
                "_id": "3",
                "_version": 1,
                "_shards": {
                    "total": 2,
                    "successful": 1,
                    "failed": 0
                },
                "status": 201
            }
        }
    ]
}

你可能感兴趣的:(elasticsearch,elasticsearch)