词项查询
使用 terms
查询在同一字段中搜索多个词项。例如,以下查询搜索 ID 为 61809
和 61810
的行
GET shakespeare/_search
{
"query": {
"terms": {
"line_id": [
"61809",
"61810"
]
}
}
}
如果文档与数组中的任何词项匹配,则返回该文档。
默认情况下,terms
查询允许的最大词项数为 65,536。要更改最大词项数,请更新 index.max_terms_count
设置。
为了获得更好的查询性能,请以排序顺序(按 UTF-8 字节值升序排列)传递包含词项的长数组。
词项查询的结果高亮显示功能可能无法保证,具体取决于高亮显示器类型和查询中的词项数量。
参数
该查询接受以下参数。所有参数均为可选。
参数 | 数据类型 | 描述 |
---|---|---|
<field> | 字符串 | 要搜索的字段。仅当文档的字段值与至少一个词项精确匹配(包括正确的间距和大小写)时,才会在结果中返回该文档。 |
提升 | 浮点数 | 一个浮点值,指定此字段对相关性得分的权重。高于 1.0 的值会增加字段的相关性。介于 0.0 和 1.0 之间的值会降低字段的相关性。默认值为 1.0。 |
_name | 字符串 | 用于查询标记的查询名称。可选。 |
value_type | 字符串 | 指定用于过滤的值类型。有效值为 default 和 bitmap 。如果省略,则默认值为 default 。 |
词项查找
词项查找检索单个文档的字段值,并将其用作搜索词项。您可以使用词项查找来搜索大量词项。
要使用词项查找,您必须启用 _source
映射字段,因为词项查找从文档中获取值。_source
字段默认启用。
词项查找尝试从本地数据节点上的分片获取文档字段值。因此,使用具有单个主分片并在所有适用数据节点上具有完整副本的索引可以减少网络流量。
示例
举例来说,创建一个包含学生数据的索引,将 student_id
映射为 keyword
PUT students
{
"mappings": {
"properties": {
"student_id": { "type": "keyword" }
}
}
}
接下来,索引三个与学生对应的文档
PUT students/_doc/1
{
"name": "Jane Doe",
"student_id" : "111"
}
PUT students/_doc/2
{
"name": "Mary Major",
"student_id" : "222"
}
PUT students/_doc/3
{
"name": "John Doe",
"student_id" : "333"
}
创建一个单独的索引,其中包含班级信息,包括班级名称和与班级中注册学生对应的学生 ID 数组
PUT classes/_doc/101
{
"name": "CS101",
"enrolled" : ["111" , "222"]
}
要搜索注册 CS101
班级的学生,请指定与该班级对应的文档 ID、该文档的索引以及词项所在字段的路径
GET students/_search
{
"query": {
"terms": {
"student_id": {
"index": "classes",
"id": "101",
"path": "enrolled"
}
}
}
}
响应包含 students
索引中所有学生(其 ID 与 enrolled
数组中的某个值匹配)的文档
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "students",
"_id": "1",
"_score": 1,
"_source": {
"name": "Jane Doe",
"student_id": "111"
}
},
{
"_index": "students",
"_id": "2",
"_score": 1,
"_source": {
"name": "Mary Major",
"student_id": "222"
}
}
]
}
}
示例:嵌套字段
第二个示例演示了查询嵌套字段。考虑一个包含以下文档的索引
PUT classes/_doc/102
{
"name": "CS102",
"enrolled_students" : {
"id_list" : ["111" , "333"]
}
}
要搜索注册 CS102
的学生,请使用点路径表示法在 path
参数中指定字段的完整路径
GET students/_search
{
"query": {
"terms": {
"student_id": {
"index": "classes",
"id": "102",
"path": "enrolled_students.id_list"
}
}
}
}
响应包含匹配文档:
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "students",
"_id": "1",
"_score": 1,
"_source": {
"name": "Jane Doe",
"student_id": "111"
}
},
{
"_index": "students",
"_id": "3",
"_score": 1,
"_source": {
"name": "John Doe",
"student_id": "333"
}
}
]
}
}
参数
下表列出了词项查找参数。
参数 | 数据类型 | 描述 |
---|---|---|
index | 字符串 | 要从中获取字段值的索引名称。必需。 |
id | 字符串 | 要从中获取字段值的文档 ID。必需。 |
路径 | 字符串 | 要从中获取字段值的字段名称。使用点路径表示法指定嵌套字段。必需。 |
路由 | 字符串 | 要从中获取字段值的文档的自定义路由值。可选。如果在索引文档时提供了自定义路由值,则为必需。 |
存储 | 布尔型 | 是否对存储字段而不是 _source 执行查找。可选。 |
位图过滤
2.17 版本引入
terms
查询可以同时过滤多个词项。但是,当输入过滤器中的词项数量增加到很大的值(大约 10,000)时,由此产生的网络和内存开销可能会变得很大,导致查询效率低下。在这种情况下,考虑使用 roaring bitmap 对大型词项过滤器进行编码,以实现更高效的过滤。
以下示例假设您有两个索引:一个 products
索引,其中包含公司销售的所有产品;另一个 customers
索引,其中存储了代表拥有特定产品的客户的过滤器。
首先,创建一个 products
索引并将 product_id
映射为整数
PUT /products
{
"mappings": {
"properties": {
"product_id": { "type": "integer" }
}
}
}
接下来,索引三个与产品对应的文档
PUT /products/_doc/1
{
"name": "Product 1",
"product_id" : 111
}
PUT /products/_doc/2
{
"name": "Product 2",
"product_id" : 222
}
PUT /products/_doc/3
{
"name": "Product 3",
"product_id" : 333
}
为了存储客户位图过滤器,您将在 customers
索引中创建一个 customer_filter
二进制字段。将 store
指定为 true
以存储该字段
PUT /customers
{
"mappings": {
"properties": {
"customer_filter": {
"type": "binary",
"store": true
}
}
}
}
对于每个客户,您需要生成一个位图,表示客户拥有的产品 ID。此位图有效地编码了该客户的过滤条件。在此示例中,您将为 ID 为 customer123
且拥有产品 111
、222
和 333
的客户创建一个 terms
过滤器。
要为客户编码 terms
过滤器,首先为该过滤器创建一个 roaring bitmap。此示例使用 [PyRoaringBitMap] 库创建位图,因此首先运行 pip install pyroaring
来安装该库。然后序列化位图并使用 Base64 编码方案对其进行编码
from pyroaring import BitMap
import base64
# Create a bitmap, serialize it into a byte string, and encode into Base64
bm = BitMap([111, 222, 333]) # product ids owned by a customer
encoded = base64.b64encode(BitMap.serialize(bm))
# Convert the Base64-encoded bytes to a string for storage or transmission
encoded_bm_str = encoded.decode('utf-8')
# Print the encoded bitmap
print(f"Encoded Bitmap: {encoded_bm_str}")
接下来,将客户过滤器索引到 customers
索引中。该过滤器的文档 ID 与相应客户的 ID 相同(在此示例中为 customer123
)。customer_filter
字段包含您为该客户生成的位图
POST customers/_doc/customer123
{
"customer_filter": "OjAAAAEAAAAAAAIAEAAAAG8A3gBNAQ=="
}
现在,您可以在 products
索引上运行 terms
查询,以在 customers
索引中查找特定客户。因为您正在查找存储字段而不是 _source
,所以将 store
设置为 true
。在 value_type
字段中,将 terms
输入的数据类型指定为 bitmap
POST /products/_search
{
"query": {
"terms": {
"product_id": {
"index": "customers",
"id": "customer123",
"path": "customer_filter",
"store": true
},
"value_type": "bitmap"
}
}
}
您还可以直接将位图传递给 terms
查询。在此示例中,product_id
字段包含 ID 为 customer123
的客户的客户过滤器位图
POST /products/_search
{
"query": {
"terms": {
"product_id": [
"OjAAAAEAAAAAAAIAEAAAAG8A3gBNAQ=="
],
"value_type": "bitmap"
}
}
}