如何掌握Elasticsearch查询DSL

Evgeni Tcherkasski摄 Unsplash

查询elasticsearch可能会非常混乱,尤其是在您刚开始使用引擎时。 在本文中,我想为您提供一个快速入门并简化此主题。

我们的查询将发送到请求正文中的elasticsearch_search ” API。 通常,我们将使用弹性搜索客户端sdk之一 ,具体取决于我们要使用的语言。

在深入探讨之前,我想谈谈有关Elasticsearch索引编制和映射过程的几点。

索引过程

我们有两个文件:

Doc_1-“夏天,棕色的狐狸跳过了懒狗”
Doc_2-“敏捷的棕色狐狸跳过了懒狗”

这两个文档都由elasticsearch索引。 索引过程的结果是一个反向索引

文本中的每个标记都映射到相应的文档。
在编制索引的过程中,将转换文本:

  1. 字符过滤器 -一个或多个字符过滤器,用于清理文本,去除不需要的字符,例如HTML标签
  2. 标记生成器 -单标记生成器,打破了串入简单的话(令牌)
  3. 令牌过滤器 -零个或多个令牌过滤器,它们执行诸如小写令牌过滤器,停用词令牌过滤器,同义词过滤器等任务。
  4. 分析器 —字符过滤器+令牌生成器+令牌过滤器

所有这三个元素都定义了一个分析器每个索引都有一个附加的分析器 。 elasticsearch具有内置的分析器,您还可以构建自己的自定义分析器并将其附加到索引。

映射

通过elasticsearch 文档

映射是定义文档及其包含的字段的存储和索引方式的过程。 例如,使用映射定义:
  1. 哪些字符串字段应视为全文字段。
  2. 哪些字段包含数字,日期或地理位置。
  3. 日期值的格式
  4. 用于控制动态添加字段的映射的自定义规则。

创建新索引时,有三个选项:

  1. 自己定义每个字段的映射
  2. 使用动态映射,并让elasticsearch“猜测”映射
  3. 两者都使用-定义重要字段,然后让elasticsearch引擎处理其余字段。
字段和映射类型在使用之前不需要定义。 通过动态映射,仅通过索引文档即可自动添加新的字段名称。 新字段既可以添加到顶级映射类型,也可以添加到内部和字段。 elasticsearch 文档

动态映射规则:

字符串字段

文本字段可以映射为:

  1. Full-text —如果该字段是电子邮件或产品说明的正文,则该字段应映射为全文。 文本是根据分析器标记的,您可以分别搜索文本中的每个单词。
  2. Keyword -如果可能需要对结构化内容(例如电子邮件地址,主机名,状态代码或标签)建立索引,则应使用关键字字段。 该字符串被视为单个单元,并且整个字符串都已编制索引。 没有部分比赛的选择

elasticsearch动态映射是同时映射两种类型的文本字段,因此您可以通过任何方式(精确短语或部分短语)进行搜索:

{
    "name" : {
        "type" : "text" ,
        "fields" : {
            "keyword" : {
                "type" : "keyword" ,
                "ignore_above" : 256
            }
        }
    }
}

日期字段

JSON没有日期数据类型,因此Elasticsearch中的日期可以是:
1. 包含格式化日期的 字符串 ,例如“ 2015-01-01”或“ 2015/01/01 12:10:30”。
2. 一个长整数, 表示从纪元以来的毫秒
3. 整数, 表示从秒开始的秒数。 官方文件

在内部,日期会转换为UTC(如果指定了时区),并存储为一个整数,表示自纪元以来的毫秒数。”

您可以定义自定义日期格式:

{
  "mappings" : {
    "properties" : {
      "date" : {
        "type" :   "date" ,
        "format" : "yyyy-MM-dd"
      }
    }
  }
}

Elasticsearch支持其他字段类型,您可以在此处查看它们

建立我们的查询

每个查询均以“ query”子句开头

{
    "query" : {
         
    }
}

当查询Elasticsearch时,我们需要考虑两件事:

  1. 请记住,所有查询都是针对我们的倒排索引运行的。 我们为索引选择的分析器(内置或自定义)将影响我们的查询子句(小写字母,词干,删除停用词等)
  2. 每个字段的映射配置都会影响我们的查询。 例如:
  • 文本字段-我们的字段配置为全文还是关键字?
  • 日期-我们为该字段选择了哪种日期格式?
  • 数字-我们的字段类型是整数,整型还是浮点型?

在编写查询时,我们可以使用两种子句:

  1. 复合查询子句 -这将是我们的包装子句,它们可以将Leaf查询和嵌套复合查询结合在一起。
  2. 叶子查询子句 -特定字段的查询词(字段名称和值)

复合查询子句

在开始编写复合查询之前,我们需要:

  1. 确定我们是否需要为每个文档打分? 得分将告诉我们每个文档相对于其他结果的相关性。
  2. 我们需要查询哪些字段? 哪些字段控制文档的分数?

首先,让我们了解弹性搜索中上下文的概念。
在elasticsearch中,我们有两种搜索环境:

查询上下文

在查询上下文中,查询子句回答问题“ 此文档与该查询子句的匹配程度如何? ”除了决定文档是否匹配外,查询子句还计算_score元字段中的相关性得分 官方文件

每当将查询子句传递给查询参数时,查询上下文即生效。 这可以是query子句,例如布尔复合查询的mustshouldmust_not子句。

elasticsearch纪录片在每个条款文件中都提到了是否有助于最终得分。

{
  "query" : {
        "bool" : {
            "must" : [
                {
                    "match" : {
                        "street" : "ditmas"
                    }
                },
                {
                    "match" : {
                        "street" : "avenue"
                    }
                }
            ]
        }
    }
}

在上面的示例中,我们有一个must子句。 查询上下文”表示其中的叶查询影响匹配文档的分数。

这是计分算法背后的理论。
当您想按相关性对结果进行排序时,该分数非常有用。

筛选条件

过滤器上下文中,查询子句回答问题“ 此文档是否与此查询子句匹配? 答案很简单,是或否-不计算分数。 过滤器上下文主要用于过滤结构化数据,例如
1.此 timestamp 是否 在2015年到2016年之间?
2. status 字段是否设置为 published官方文件

每当将查询子句传递给过滤器参数时,过滤器上下文即生效。 例如,可以将filtermust_not参数传递给bool复合查询。

像查询上下文一样,无论子句查询是否影响评分,都应查看文档。

{
  "query" : {
    "bool" : {
      "filter" : {
        "range" : {
          "age" : {
              "gte" : 20 ,
              "lte" : 30
          }
        }
      }
    }
  }
}

在上面的示例中,我们有一个名为“ Filter context”的filter子句,这意味着其中的叶子查询不会影响匹配文档的分数。

在我们的搜索子句中,我们可以将查询和过滤器上下文与诸如bool类的复合查询结合起来。 在这种情况下,只有出现在查询上下文子句中的搜索词才会影响每个文档的分数。 如果我们只有一个过滤器上下文,那么所有文档的分数都将为零。

我们之前做出的决定将确定查询的布局。
例如,此查询将查询上下文和过滤上下文一起使用:

{
"query" : {
   "bool" : {
      "must" : {
          Leaf query clauses - affects the scoring of matching documents
      },
      "must_not" : { 
          Leaf query clauses - affects the scoring of matching documents
      },
      "should" : {   
          Leaf query clauses - affects the scoring of matching documents
      },
      "filter" : {   
         Leaf query clauses - doesn 't affects the scoring of matching documents 
      }
    }
  }
}

只有出现在must内的查询子句must_not should 子句会影响每个文档的分数(它们是查询上下文)。

Elasticsearch需要一个更匹配就是更好的办法意味着从得分mustmust_notshould将加在一起以提供最终得分。

如果我们根本不需要分数,则只能使用filter子句。 例如,如果我们搜索结构化数据或搜索诸如二进制或日期之类的确切值,我们将仅使用过滤器上下文:

{
  "query" : {
    "bool" : {
      "filter" : [
          {
            "term" : { "gender" : "female" }
          },
          {
            "range" : { "age" : { "gte" : "50" } }
          }
      ]
    }
  }
}

上面查询结果中的所有匹配文档的得分均为零。

叶子查询子句

在构建外部布局时,我们决定了查询的构建基石。 我们还决定了哪些字段将决定我们的结果得分。 如您所见,elasticsearch有很多选项,我们仅介绍了本文的基础知识。 每个复合查询可以包装其他复合查询,依此类推。 我对您的建议是尝试使其尽可能简单。

现在是时候编写我们的内部/叶子搜索查询(容器子句中的内容)了。

在这里,我们还有决定要制定

对于我们搜索的每个字段,我们需要:

确定此字段是否与文档分数相关?

  • 是的:将其放在query子句中
  • 否:应在filter子句下(请注意,过滤器只能嵌套在Boolean子句中)

检查字段的类型以及如何映射?

  • 例如,查询文本字段很棘手。 如果将文本字段映射为keyword ,那么我们只能选择以对其进行索引的确切方式进行搜索(不标记,大写/小写字母等)。

比方说,例如,我们在一个带有“注释”字段的文档中建立了索引,并且其中包含文本“ The quick BRown fox”

  • 如果notes字段被映射为Keyword,则反向索引将包含映射到该文档的“ Quick BRown fox”文本。 搜索“ Quick BRown fox”文本将完全匹配该文档。
  • 如果将notet字段映射为全文,则在倒排索引中,我们将具有令牌:[the,quick,brown,fox]分别连接到文档-搜索这些令牌或其同义词将与该文档匹配。

确定如何将文本发送给搜索引擎

当我们将查询发送到elasticsearch引擎时,我们有两个选择:

1.按原样发送

对于这种选择,我们使用术语级别查询 例如,如果您搜索短语“ Star Trek”,则查询引擎将检查“ Star Trek”的倒排索引

2.发送分析

对于这种选择,我们使用全文查询 搜索的文本将与在索引过程中传递的索引文本通过同一分析器(我们也可以提供不同的分析器作为搜索服务的属性)。 它将被标记并过滤 例如,如果您搜索短语“ Star Trek”,则查询引擎将检查[“ star”,“ trek”]的倒排索引(取决于您选择的分析仪)。

注意 :如果该字段最初是作为关键字映射的,那么您必须发送被索引的确切文本才能获得结果

在大多数情况下,我们希望在将搜索到的文本发送到搜索引擎之前对其进行分析,这样可以提供更好的结果。 但是有时我们想要搜索准确的单词或句子,通常是在数字,日期和枚举之类的数据中进行搜索。

全文查询示例


{
  "query" : {
    "match" : {
      "mail_body" : "Jeff BRidges"
    }
  }
}

字词查询示例

{
  "query" : {
    "term" : {
      "mail_from" : "emma@somemail.com"
    }
  }
}

复合查询-最后的详细示例

{
  "query" : {
    "bool" : {
      "must" : {
        "match" : {
            "mail_body" : "Jeff BRidges"
        }
      },
      "filter" : {
        "term" : {
            "mail_from" : "emma@somemail.com"
        }
      }
    }
  }
}
  • query:主查询包含
  • bool :复合查询容器
  • must :这是一个查询上下文查询,它里面的每个叶子查询都会对匹配文档的分数做出贡献
  • match :这是一个 全文查询表示文本“ Jeff BRidges” 将通过 分析器并转换为[“ jeff”,“ bridges”]。 确保仅在“ mail_body”字段映射为全文字段时才使用该选项。
  • filter :这是一个过滤器上下文查询,它里面的每个叶子查询都不会起作用 匹配文档的分数,并且考虑将子句缓存。
  • term :这是一个 术语级别查询则文本“ emma@somemail.com”将不会通过分析器,而是直接发送到搜索引擎。

最后的想法

Elasticsearch查询DSL绝对不是最简单的使用方法,但是一旦您知道如何使用它,它便可以成为功能强大的工具。 在本文中,我试图为大家提供一个查询Elasticsearch的快速入门,并鼓励您更深入地研究Elasticsearch文档

下一步

了解了本文中讨论的所有概念之后,您会发现遍历Elasticsearch文档并找到所需的所有解决方案变得更加容易。

From: https://hackernoon.com/how-to-master-elasticsearch-query-dsl-454632cg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值