Term 级别的查询
> 文档中心 > INFINI Easysearch > 功能手册 > 管理模块 > Term 级别的查询

词项级别查询 Term-level queries #

Easysearch 在搜索数据时支持两种类型的查询:term 查询和全文查询。

下表显示了它们之间的差异:

词项查询全文检索
描述term 查询回应与查询匹配的文档。全文查询回应文档与查询的匹配程度。
分词搜索 term 是不分词的。这意味着 term 查询按原样搜索您的 term。搜索 term 由索引时用于文档指定字段的分词器进行分词。这意味着您的搜索词将经历与文档字段相同的分词过程。
相关性Term 级查询只返回匹配的文档,而不根据相关性得分对其进行排序。他们仍然计算相关性得分,但该得分对于返回的所有文档都是相同的。全文查询计算每个匹配的相关性得分,并按相关性的降序对结果进行排序。
应用场景当您希望匹配数字、日期、 tag 等精确值,并且不需要按相关性对匹配项进行排序时,请使用术语级查询。在考虑大小写和词干变体等因素后,使用全文查询来匹配文本字段并按相关性排序。

Easysearch 使用名为 Okapi BM25 的概率排名框架来计算相关性得分。要了解更多关于 Okapi BM25 的信息,请参阅 维基百科.

假设您在 Easysearch 集群中索引了莎士比亚全集。我们使用 term 查询在 text_entry 字段中搜索短语 “To be,or not be”:

GET shakespeare/_search
{
  "query": {
    "term": {
      "text_entry": "To be, or not to be"
    }
  }
}

响应示例 #

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  }
}

我们没有找回任何匹配( hits )。这是因为 term “To be, or not to be”是在倒排索引中按字面搜索的,其中只存储文本字段的分词后的值。Term 查询不适合搜索分词的文本字段,因为它们通常会产生意外的结果。使用文本数据时,仅对仅映射为 keyword 的字段使用 term 查询。

使用全文查询:

GET shakespeare/_search
{
  "query": {
    "match": {
      "text_entry": "To be, or not to be"
    }
  }
}

搜索查询 “To be,or not be” 被分析并标记为一个标记数组,就像文档的 text_entry 字段一样。全文查询在搜索查询和所有文档的 text_entry 字段之间执行标记的交集,然后根据相关性得分对结果进行排序:

响应示例 #

{
  "took" : 19,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10000,
      "relation" : "gte"
    },
    "max_score" : 17.419369,
    "hits" : [
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "34229",
        "_score" : 17.419369,
        "_source" : {
          "type" : "line",
          "line_id" : 34230,
          "play_name" : "Hamlet",
          "speech_number" : 19,
          "line_number" : "3.1.64",
          "speaker" : "HAMLET",
          "text_entry" : "To be, or not to be: that is the question:"
        }
      },
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "109930",
        "_score" : 14.883024,
        "_source" : {
          "type" : "line",
          "line_id" : 109931,
          "play_name" : "A Winters Tale",
          "speech_number" : 23,
          "line_number" : "4.4.153",
          "speaker" : "PERDITA",
          "text_entry" : "Not like a corse; or if, not to be buried,"
        }
      },
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "103117",
        "_score" : 14.782743,
        "_source" : {
          "type" : "line",
          "line_id" : 103118,
          "play_name" : "Twelfth Night",
          "speech_number" : 53,
          "line_number" : "1.3.95",
          "speaker" : "SIR ANDREW",
          "text_entry" : "will not be seen; or if she be, its four to one"
        }
      }
    ]
  }
}
...

有关所有全文查询的列表,请参见 全文查询

如果您想在 speaker 字段中查询类似 “HAMLET” 的准确术语,并且不需要根据相关性得分对结果进行排序,则 term 查询更有效:

GET shakespeare/_search
{
  "query": {
    "term": {
      "speaker": "HAMLET"
    }
  }
}

响应示例 #

{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1582,
      "relation" : "eq"
    },
    "max_score" : 4.2540946,
    "hits" : [
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "32700",
        "_score" : 4.2540946,
        "_source" : {
          "type" : "line",
          "line_id" : 32701,
          "play_name" : "Hamlet",
          "speech_number" : 9,
          "line_number" : "1.2.66",
          "speaker" : "HAMLET",
          "text_entry" : "[Aside]  A little more than kin, and less than kind."
        }
      },
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "32702",
        "_score" : 4.2540946,
        "_source" : {
          "type" : "line",
          "line_id" : 32703,
          "play_name" : "Hamlet",
          "speech_number" : 11,
          "line_number" : "1.2.68",
          "speaker" : "HAMLET",
          "text_entry" : "Not so, my lord; I am too much i' the sun."
        }
      },
      {
        "_index" : "shakespeare",
        "_type" : "_doc",
        "_id" : "32709",
        "_score" : 4.2540946,
        "_source" : {
          "type" : "line",
          "line_id" : 32710,
          "play_name" : "Hamlet",
          "speech_number" : 13,
          "line_number" : "1.2.75",
          "speaker" : "HAMLET",
          "text_entry" : "Ay, madam, it is common."
        }
      }
    ]
  }
}
...

Term 查询精确匹配。所以,如果你搜索 “Hamlet” ,你不会得到任何匹配,因为 “HAMLET” 是一个 keyword 字段,它是按字面意思存储在 Easysearch 中,而不是以分词的形式存储的。 搜索查询“HAMLET”也按字面搜索。因此,要在该字段上获得匹配,我们需要输入完全相同的字符。


Term 查询 #

term 查询在字段中搜索精确的 term。

GET shakespeare/_search
{
  "query": {
    "term": {
      "line_id": {
        "value": "61809"
      }
    }
  }
}

Terms 查询 #

terms 查询在同一字段中搜索多个 term。

GET shakespeare/_search
{
  "query": {
    "terms": {
      "line_id": [
        "61809",
        "61810"
      ]
    }
  }
}

你会得到符合任何 term 的文档。

IDs #

ids 查询搜索一个或多个文档 ID 值。

GET shakespeare/_search
{
  "query": {
    "ids": {
      "values": [
        34229,
        91296
      ]
    }
  }
}

Range #

范围 查询搜索字段中的值范围。

要搜索 line_id 值 >= 10 and <= 20 的文档,请执行以下操作:

GET shakespeare/_search
{
  "query": {
    "range": {
      "line_id": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}
参数行为
gte大于等于。
gt大于。
lte小于等于。
lt小于。

假设您有一个 products 索引,并且希望查找 2023 年添加的所有产品:

GET products/_search
{
  "query": {
    "range": {
      "created": {
        "gte": "2023/01/01",
        "lte": "2023/12/31"
      }
    }
  }
}

使用基本数学表达式指定相对日期。

从指定日期减去 1 年零 1 天:

GET products/_search
{
  "query": {
    "range": {
      "created": {
        "gte": "2023/01/01||-1y-1d"
      }
    }
  }
}

我们指定的第一个日期是定位日期或日期数学的起点。添加两个拖曳管道符号。然后你可以加一天( +1d )或减去两周( -2w )。此数学表达式与您指定的定位日期相关。

您还可以通过在日期或时间单位中添加正斜杠来舍入日期。

要查找上一年添加并按月份四舍五入的产品:

GET products/_search
{
  "query": {
    "range": {
      "created": {
        "gte": "now-1y/M"
      }
    }
  }
}

关键字 now 指向当前日期和时间。

前缀 Prefix #

prefix 查询搜索以特定前缀开头的 term。

GET shakespeare/_search
{
  "query": {
    "prefix": {
      "speaker": "KING"
    }
  }
}

是否存在 Exists #

exists 查询搜索包含特定字段的文档。

GET shakespeare/_search
{
  "query": {
    "exists": {
      "field": "speaker"
    }
  }
}

通配符 Wildcards #

通配符查询搜索与通配符模式匹配的 term。

特征行为
*匹配所有有效值。
?匹配单个有效值。

要搜索以 H 开头并以 Y 结尾的 term :

GET shakespeare/_search
{
  "query": {
    "wildcard": {
      "speaker": {
        "value": "H*Y"
      }
    }
  }
}

如果我们将 * 更改为 ,我们得不到匹配,因为 代表单个字符。

通配符查询往往很慢,因为它们需要遍历大量术语。避免在查询的开头放置通配符,因为这可能是一个资源和时间都非常昂贵的操作。

正则 Regex #

使用 regex 查询搜索与正则表达式匹配的 term。

此正则表达式匹配任何单个大写或小写字母:

GET shakespeare/_search
{
  "query": {
    "regexp": {
      "play_name": "H[a-zA-Z]+mlet"
    }
  }
}

正则表达式应用于字段中的 term ,而不是字段的整个值。

正则表达式的效率在很大程度上取决于您编写的模式。确保使用前缀或后缀编写 regex 查询以提高性能。