索引
如何索引和搜索 JSON 文档
除了索引 Redis 哈希之外,Redis Stack 还可以索引 JSON 文档。
先决条件
在索引和搜索 JSON 文档之前,您需要一个具有以下任一功能的数据库:
- Redis Stack,自动包含 JSON 以及搜索和查询功能
- Redis v6.x 或更高版本,安装并启用以下模块:
- RediSearch v2.2 或更高版本
- RedisJSON v2.0 或更高版本
使用 JSON 架构创建索引
使用命令创建索引时FT.CREATE,请包含ON JSON关键字来索引数据库中存储的任何现有和未来的 JSON 文档。
要定义SCHEMA,您可以提供JSONPath表达式。每个 JSONPath 表达式的结果都已编入索引,并与名为attribute(以前称为field)的逻辑名称相关联。您可以在查询中使用这些属性。
使用以下语法创建 JSON 索引:
FT.CREATE {index_name} ON JSON SCHEMA {json_path} AS {attribute} {type}
例如,此命令创建一个索引,该索引对代表库存项目的每个 JSON 文档的名称、描述、价格和图像向量嵌入进行索引:
127.0.0.1:6379> FT.CREATE itemIdx ON JSON PREFIX 1 item: SCHEMA $.name AS name TEXT $.description as description TEXT $.price AS price NUMERIC $.embedding AS embedding VECTOR FLAT 6 DIM 4 DISTANCE_METRIC L2 TYPE FLOAT32
有关 JSON 索引限制的更多详细信息,请参阅索引限制SCHEMA。
添加 JSON 文档
创建索引后,Redis Stack 会自动为数据库中存储的任何现有、已修改或新创建的 JSON 文档编制索引。对于现有文档,索引编制在后台异步运行,因此文档可能需要一些时间才能使用。已修改和新创建的文档会同步编制索引,因此在添加或修改命令完成时,文档将可用。
您可以使用任何 JSON 写入命令(例如JSON.SET和JSON.ARRAPPEND)来创建或修改 JSON 文档。
以下示例使用这些 JSON 文档来表示单个库存项目。
第 1 项 JSON 文档:
{
"name": "Noise-cancelling Bluetooth headphones",
"description": "Wireless Bluetooth headphones with noise-cancelling technology",
"connection": {
"wireless": true,
"type": "Bluetooth"
},
"price": 99.98,
"stock": 25,
"colors": [
"black",
"silver"
],
"embedding": [0.87, -0.15, 0.55, 0.03]
}
第 2 项 JSON 文档:
{
"name": "Wireless earbuds",
"description": "Wireless Bluetooth in-ear headphones",
"connection": {
"wireless": true,
"type": "Bluetooth"
},
"price": 64.99,
"stock": 17,
"colors": [
"black",
"white"
],
"embedding": [-0.7, -0.51, 0.88, 0.14]
}
用于JSON.SET将这些文档存储在数据库中:
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","connection":{"wireless":true,"type":"Bluetooth"},"price":99.98,"stock":25,"colors":["black","silver"],"embedding":[0.87,-0.15,0.55,0.03]}'
"OK"
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":64.99,"stock":17,"colors":["black","white"],"embedding":[-0.7,-0.51,0.88,0.14]}'
"OK"
由于在这种情况下索引是同步的,因此命令返回后文档将立即在索引中可用JSON.SET。任何与索引内容匹配的后续查询都将返回该文档。
搜索索引
要在索引中搜索 JSON 文档,请使用命令FT.SEARCH。您可以搜索 中定义的任何属性SCHEMA。
例如,使用此查询搜索名称中带有单词“earbuds”的商品:
127.0.0.1:6379> FT.SEARCH itemIdx '@name:(earbuds)'
1) "1"
2) "item:2"
3) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"connection\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embedding\":[-0.7,-0.51,0.88,0.14]}"
此查询搜索描述中包含“蓝牙”和“耳机”的所有项目:
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(bluetooth headphones)'
1) "2"
2) "item:1"
3) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"], \"embedding\":[0.87,-0.15,0.55,0.03]}"
4) "item:2"
5) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"connection\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embedding\":[-0.7,-0.51,0.88,0.14]}"
现在搜索价格在70以下的蓝牙耳机:
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(bluetooth headphones) @price:[0 70]'
1) "1"
2) "item:2"
3) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"connection\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embedding\":[-0.7,-0.51,0.88,0.14]}"
最后,搜索与嵌入为 [1.0, 1.0, 1.0, 1.0] 的图像最相似的蓝牙耳机:
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(bluetooth headphones)=>[KNN 2 @embedding $blob]' PARAMS 2 blob \x01\x01\x01\x01 DIALECT 2
1) "2"
2) "item:1"
3) 1) "__embedding_score"
2) "1.08280003071"
1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"embedding\":[0.87,-0.15,0.55,0.03]}"
2) "item:2"
3) 1) "__embedding_score"
2) "1.54409992695"
3) "$"
4) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"connection\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embedding\":[-0.7,-0.51,0.88,0.14]}"
有关搜索查询的更多信息,请参阅搜索查询语法。
将 JSON 数组索引为 TAG
使用 JSON数组为具有多值术语的 JSON 字段建立索引的首选方法是使用 JSON 数组。数组的每个值都已建立索引,并且这些值必须是标量。如果要将字符串或布尔值作为 JSON 数组中的标签建立索引,请使用JSONPath通配符运算符。
要索引某个项目的可用颜色列表,请在索引创建期间$.colors.*在定义中指定 JSONPath :SCHEMA
127.0.0.1:6379> FT.CREATE itemIdx2 ON JSON PREFIX 1 item: SCHEMA $.colors.* AS colors TAG $.name AS name TEXT $.description as description TEXT
现在您可以搜索银色耳机:
127.0.0.1:6379> FT.SEARCH itemIdx2 "@colors:{silver} (@name:(headphones)|@description:(headphones))"
1) "1"
2) "item:1"
3) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"]}"
将 JSON 数组作为文本进行索引
从 RediSearch v2.6.0 开始,可以在字符串数组或指向多个字符串的 JSONPath 上进行全文搜索。
如果要将多个字符串值索引为 TEXT,请使用指向单个字符串数组的 JSONPath,或指向多个字符串值的 JSONPath,并使用 JSONPath 运算符(例如通配符、过滤器、联合、数组切片和/或递归下降)。
要索引某个项目的可用颜色列表,请在索引创建期间$.colors在定义中指定 JSONPath :SCHEMA
127.0.0.1:6379> FT.CREATE itemIdx3 ON JSON PREFIX 1 item: SCHEMA $.colors AS colors TEXT $.name AS name TEXT $.description as description TEXT
127.0.0.1:6379> JSON.SET item:3 $ '{"name":"True Wireless earbuds","description":"True Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":74.99,"stock":20,"colors":["red","light blue"]}'
"OK"
现在您可以对浅色耳机进行全文搜索:
127.0.0.1:6379> FT.SEARCH itemIdx3 '@colors:(white|light) (@name|description:(headphones))' RETURN 1 $.colors
1) (integer) 2
2) "item:2"
3) 1) "$.colors"
2) "[\"black\",\"white\"]"
4) "item:3"
5) 1) "$.colors"
2) "[\"red\",\"light blue\"]"
限制
-
当 JSONPath 可能导致多个值而不仅仅是单个数组时(例如,当 JSONPath 包含通配符等时),指定
SLOP或INORDER将FT.SEARCH返回错误,因为与 JSONPath 匹配的值的顺序未明确定义,从而导致可能不一致的结果。$..b[*]例如,在 JSON 值上使用 JSONPath,例如{ "a": [ {"b": ["first first", "first second"]}, {"c": {"b": ["second first", "second second"]}}, {"b": ["third first", "third second"]} ] }可能会按各种顺序匹配值,具体取决于所使用的 JSONPath 库的具体实现。
由于
SLOP和INORDER考虑索引值之间的相对顺序,并且结果可能会在未来版本中发生变化,因此将返回错误。 -
当 JSONPath 导致多个值时:
- 字符串值已编入索引
null值被跳过- 任何其他值类型都会导致索引失败
-
SORTBY仅按第一个值排序 -
不
HIGHLIGHT支持 -
RETURNSchema 属性的 JSONPath 指向多个值,仅返回第一个值(作为 JSON 字符串) -
如果 JSONPath 由 而不是 Schema 属性指定
RETURN,则返回所有值(作为 JSON 字符串)
处理不同数组槽中的短语:
索引时,使用预定义的增量来增加多个文本值的数组槽之间的位置偏移。此增量控制不同数组槽中短语之间的分隔级别(与SLOP的参数相关FT.SEARCH)。此预定义值由配置参数设置MULTI_TEXT_SLOP(在模块加载时)。默认值为 100。
将 JSON 数组索引为 NUMERIC
从 RediSearch v2.6.1 开始,可以在数值数组或导致多个数值的 JSONPath 上进行搜索。
如果要将多个数值索引为 NUMERIC,请使用指向单个数字数组的 JSONPath,或指向多个数字的 JSONPath,并使用 JSONPath 运算符(例如通配符、过滤器、联合、数组切片和/或递归下降)。
max_level例如,将可用的音量(以分贝为单位)添加到项目列表中:
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","connection":{"wireless":true,"type":"Bluetooth"},"price":99.98,"stock":25,"colors":["black","silver"], "max_level":[60, 70, 80, 90, 100]}'
OK
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":64.99,"stock":17,"colors":["black","white"], "max_level":[80, 100, 120]}'
OK
127.0.0.1:6379> JSON.SET item:3 $ '{"name":"True Wireless earbuds","description":"True Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":74.99,"stock":20,"colors":["red","light blue"], "max_level":[90, 100, 110, 120]}'
OK
要索引数组,请在索引创建期间在定义中max_level指定 JSONPath :$.max_levelSCHEMA
127.0.0.1:6379> FT.CREATE itemIdx4 ON JSON PREFIX 1 item: SCHEMA $.max_level AS dB NUMERIC
OK
您现在可以搜索具有特定最大音量级别的耳机,例如,在 70 到 80 之间(含),返回max_level数组中至少有一个值在请求范围内的项目:
127.0.0.1:6379> FT.SEARCH itemIdx4 '@dB:[70 80]'
1) (integer) 2
2) "item:1"
3) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"max_level\":[60,70,80,90,100]}"
4) "item:2"
5) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"max_level\":[80,100,120]}"
您还可以搜索所有值都在特定范围内的项目。例如,所有值都在 [90, 120] 范围内(含):
127.0.0.1:6379> FT.SEARCH itemIdx4 '-@dB:[-inf (90] -@dB:[(120 +inf]'
1) (integer) 1
2) "item:3"
3) 1) "$"
2) "{\"name\":\"True Wireless earbuds\",\"description\":\"True Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":74.99,\"stock\":20,\"colors\":[\"red\",\"light blue\"],\"max_level\":[90,100,110,120]}"
限制
当 JSONPath 导致多个数值时:
- 数值被索引
null值被跳过- 任何其他值类型都会导致索引失败
将 JSON 数组作为 GEO 进行索引
从 RediSearch v2.6.1 开始,可以对 geo(地理)值数组或导致多个地理值的 JSONPath 进行搜索。
在 RediSearch v2.6.1 之前,每个 GEO 属性仅支持一个地理值。地理值使用逗号分隔的字符串指定,格式为“经度,纬度”。例如,“15.447083,78.238306”。
在 RediSearch v2.6.1 中,还支持此类地理值的 JSON 数组。
为了索引多个地理值,用户可以使用指向单个地理值数组的 JSONPath,或者指向多个地理值的 JSONPath,使用 JSONPath 运算符(例如通配符、过滤器、联合、数组切片和/或递归下降)。
null值被跳过- 其他值将导致索引失败(布尔值、数字、对象、数组、格式错误的 GEO 字符串、无效坐标)
例如,将 添加到商品列表中vendor_id,即可以实际购买商品的位置:
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","connection":{"wireless":true,"type":"Bluetooth"},"price":99.98,"stock":25,"colors":["black","silver"], "max_level":[60, 70, 80, 90, 100], "vendor_id": [100,300]}'
OK
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":64.99,"stock":17,"colors":["black","white"], "max_level":[80, 100, 120], "vendor_id": [100,200]}'
OK
127.0.0.1:6379> JSON.SET item:3 $ '{"name":"True Wireless earbuds","description":"True Wireless Bluetooth in-ear headphones","connection":{"wireless":true,"type":"Bluetooth"},"price":74.99,"stock":20,"colors":["red","light blue"], "max_level":[90, 100, 110, 120], "vendor_id": [100]}'
OK
现在添加一些供应商及其地理位置:
127.0.0.1:6379> JSON.SET vendor:1 $ '{"id":100, "name":"Kwik-E-Mart", "location":["35.213,31.785", "35.178,31.768", "35.827,31.984"]}'
OK
127.0.0.1:6379> JSON.SET vendor:2 $ '{"id":200, "name":"Cypress Creek", "location":["34.638,31.79", "34.639,31.793"]}'
OK
127.0.0.1:6379> JSON.SET vendor:3 $ '{"id":300, "name":"Barneys", "location":["34.648,31.817", "34.638,31.806", "34.65,31.785"]}'
OK
要索引数字数组,请在索引创建期间在定义中vendor_id指定 JSONPath :$.vendor_idSCHEMA
127.0.0.1:6379> FT.CREATE itemIdx5 ON JSON PREFIX 1 item: SCHEMA $.vendor_id AS vid NUMERIC
OK
要索引地理数组,请在索引创建期间在定义中location指定 JSONPath :$.locationSCHEMA
127.0.0.1:6379> FT.CREATE vendorIdx ON JSON PREFIX 1 vendor: SCHEMA $.location AS loc GEO
OK
现在搜索特定位置附近的供应商。例如,客户位于地理坐标 34.5,31.5,而您想要获取距离我们位置 40 公里范围内的供应商:
127.0.0.1:6379> FT.SEARCH vendorIdx '@loc:[34.5 31.5 40 km]' return 1 $.id
1) (integer) 2
2) "vendor:2"
3) 1) "$.id"
1) "200"
4) "vendor:3"
5) 1) "$.id"
1) "300"
现在寻找这些供应商提供的产品:
127.0.0.1:6379> FT.SEARCH itemIdx5 '@vid:[200 300]'
1) (integer) 2
2) "item:2"
3) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"max_level\":[80,100,120],\"vendor_id\":[100,200]}"
4) "item:1"
5) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"max_level\":[60,70,80,90,100],\"vendor_id\":[100,300]}"
将 JSON 数组作为 VECTOR 进行索引
从 RediSearch 2.6.0 开始,您可以在索引模式中将 JSONPath 索引为 VECTOR 类型的数值数组。
例如,假设您的 JSON 项目包含一个向量嵌入数组,其中每个向量代表一个产品的图像。要为这些向量编制索引,请$.embedding在索引创建期间在架构定义中指定 JSONPath:
127.0.0.1:6379> FT.CREATE itemIdx5 ON JSON PREFIX 1 item: SCHEMA $.embedding AS embedding VECTOR FLAT 6 DIM 4 DISTANCE_METRIC L2 TYPE FLOAT32
OK
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","price":99.98,"stock":25,"colors":["black","silver"],"embedding":[0.87,-0.15,0.55,0.03]}'
OK
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","price":64.99,"stock":17,"colors":["black","white"],"embedding":[-0.7,-0.51,0.88,0.14]}'
OK
现在,您可以使用向量搜索 KNN 查询来搜索与图像嵌入最相似的两副耳机。(请注意,从方言 2 开始支持向量查询。)例如:
127.0.0.1:6379> FT.SEARCH itemIdx5 '*=>[KNN 2 @embedding $blob AS dist]' SORTBY dist PARAMS 2 blob \x01\x01\x01\x01 DIALECT 2
1) (integer) 2
2) "item:1"
3) 1) "dist"
2) "1.08280003071"
3) "$"
4) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"embedding\":[0.87,-0.15,0.55,0.03]}"
4) "item:2"
5) 1) "dist"
2) "1.54409992695"
3) "$"
4) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embedding\":[-0.7,-0.51,0.88,0.14]}"
如果要将多个数字数组索引为 VECTOR,请使用JSONPath运算符(例如通配符、过滤器、联合、数组切片和/或递归下降)指向多个数字数组。
例如,假设您的 JSON 项目包含一个向量嵌入数组,其中每个向量代表同一产品的不同图像。要为这些向量编制索引,请$.embeddings[*]在索引创建期间在架构定义中指定 JSONPath:
127.0.0.1:6379> FT.CREATE itemIdx5 ON JSON PREFIX 1 item: SCHEMA $.embeddings[*] AS embeddings VECTOR FLAT 6 DIM 4 DISTANCE_METRIC L2 TYPE FLOAT32
OK
127.0.0.1:6379> JSON.SET item:1 $ '{"name":"Noise-cancelling Bluetooth headphones","description":"Wireless Bluetooth headphones with noise-cancelling technology","price":99.98,"stock":25,"colors":["black","silver"],"embeddings":[[0.87,-0.15,0.55,0.03]]}'
OK
127.0.0.1:6379> JSON.SET item:2 $ '{"name":"Wireless earbuds","description":"Wireless Bluetooth in-ear headphones","price":64.99,"stock":17,"colors":["black","white"],"embeddings":[[-0.7,-0.51,0.88,0.14],[-0.8,-0.15,0.33,-0.01]]}'
OK
$.embedding在 VECTOR 类型的架构中)不允许您索引存储在该字段下的多个向量。因此,如果您将其设置$.embedding为索引架构的路径,则在 JSON 中的字段中指定向量数组embedding将导致索引失败。现在,您可以使用向量搜索 KNN 查询来搜索与图像嵌入最相似的两款耳机。(请注意,从方言 2 开始支持向量查询。)文档与查询向量之间的距离定义为查询向量与与架构中指定的 JSONPath 匹配的向量之间的最小距离。例如:
127.0.0.1:6379> FT.SEARCH itemIdx5 '*=>[KNN 2 @embeddings $blob AS dist]' SORTBY dist PARAMS 2 blob \x01\x01\x01\x01 DIALECT 2
1) (integer) 2
2) "item:2"
3) 1) "dist"
2) "0.771500051022"
3) "$"
4) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"],\"embeddings\":[[-0.7,-0.51,0.88,0.14],[-0.8,-0.15,0.33,-0.01]]}"
4) "item:1"
5) 1) "dist"
2) "1.08280003071"
3) "$"
4) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"],\"embeddings\":[[0.87,-0.15,0.55,0.03]]}"
请注意,0.771500051022是查询向量与[-0.8,-0.15,0.33,-0.01]嵌入数组中的第二个元素之间的 L2 距离,并且它低于查询向量与[-0.7,-0.51,0.88,0.14]嵌入数组中的第一个元素之间的 L2 距离。
有关向量相似性语法的更多信息,请参阅向量场。
索引 JSON 对象
您无法索引 JSON 对象。如果 JSONPath 表达式返回一个对象,它将被忽略。
要对 JSON 对象的内容进行索引,您需要在单独的属性中对对象内的各个元素进行索引。
例如,要索引connectionJSON 对象,请在创建索引时将$.connection.wireless和字段定义为单独的属性:$.connection.type
127.0.0.1:6379> FT.CREATE itemIdx3 ON JSON SCHEMA $.connection.wireless AS wireless TAG $.connection.type AS connectionType TEXT
"OK"
创建新索引后,您可以搜索无线标签设置为的项目true:
127.0.0.1:6379> FT.SEARCH itemIdx3 '@wireless:{true}'
1) "2"
2) "item:2"
3) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"connection\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"]}"
4) "item:1"
5) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"]}"
您还可以搜索具有蓝牙连接类型的商品:
127.0.0.1:6379> FT.SEARCH itemIdx3 '@connectionType:(bluetooth)'
1) "2"
2) "item:1"
3) 1) "$"
2) "{\"name\":\"Noise-cancelling Bluetooth headphones\",\"description\":\"Wireless Bluetooth headphones with noise-cancelling technology\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":99.98,\"stock\":25,\"colors\":[\"black\",\"silver\"]}"
4) "item:2"
5) 1) "$"
2) "{\"name\":\"Wireless earbuds\",\"description\":\"Wireless Bluetooth in-ear headphones\",\"connection\":{\"wireless\":true,\"type\":\"Bluetooth\"},\"price\":64.99,\"stock\":17,\"colors\":[\"black\",\"white\"]}"
场投影
FT.SEARCH默认返回整个 JSON 文档。如果希望将返回的搜索结果限制到特定的属性,可以使用字段投影。
返回特定属性
运行搜索查询时,您可以使用RETURN关键字指定要在搜索结果中包含的属性。您还需要指定要返回的字段数。
例如,此查询仅返回每组耳机的name和:price
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(headphones)' RETURN 2 name price
1) "2"
2) "item:1"
3) 1) "name"
2) "Noise-cancelling Bluetooth headphones"
3) "price"
4) "99.98"
4) "item:2"
5) 1) "name"
2) "Wireless earbuds"
3) "price"
4) "64.99"
带有 JSONPath 的项目
您可以在语句中使用JSONPath表达式RETURN来提取 JSON 文档的任何部分,甚至是索引中未定义的字段SCHEMA。
例如,以下查询使用 JSONPath 表达式$.stock除了返回名称和价格属性之外,还返回每件商品的库存。
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(headphones)' RETURN 3 name price $.stock
1) "2"
2) "item:1"
3) 1) "name"
2) "Noise-cancelling Bluetooth headphones"
3) "price"
4) "99.98"
5) "$.stock"
6) "25"
4) "item:2"
5) 1) "name"
2) "Wireless earbuds"
3) "price"
4) "64.99"
5) "$.stock"
6) "17"
请注意,返回的属性名称是 JSONPath 表达式本身:"$.stock"。
您可以使用AS选项为返回的属性指定别名:
127.0.0.1:6379> FT.SEARCH itemIdx '@description:(headphones)' RETURN 5 name price $.stock AS stock
1) "2"
2) "item:1"
3) 1) "name"
2) "Noise-cancelling Bluetooth headphones"
3) "price"
4) "99.98"
5) "stock"
6) "25"
4) "item:2"
5) 1) "name"
2) "Wireless earbuds"
3) "price"
4) "64.99"
5) "stock"
6) "17"
此查询将字段作为别名"stock"而不是 JSONPath 表达式返回"$.stock"。
突出显示搜索词
您可以在任何索引属性中突出显示相关的搜索词TEXT。
对于FT.SEARCH,您必须明确设置要在RETURN和HIGHLIGHT参数后突出显示的属性。
使用可选TAGS关键字来指定围绕(或突出显示)匹配搜索词的字符串。
例如,在项目名称和描述中使用粗体 HTML 标签突出显示单词“蓝牙”:
127.0.0.1:6379> FT.SEARCH itemIdx '(@name:(bluetooth))|(@description:(bluetooth))' RETURN 3 name description price HIGHLIGHT FIELDS 2 name description TAGS '<b>' '</b>'
1) "2"
2) "item:1"
3) 1) "name"
2) "Noise-cancelling <b>Bluetooth</b> headphones"
3) "description"
4) "Wireless <b>Bluetooth</b> headphones with noise-cancelling technology"
5) "price"
6) "99.98"
4) "item:2"
5) 1) "name"
2) "Wireless earbuds"
3) "description"
4) "Wireless <b>Bluetooth</b> in-ear headphones"
5) "price"
6) "64.99"
使用 JSONPath 进行聚合
您可以使用聚合来生成统计数据或构建方面查询。
该LOAD选项接受JSONPath表达式。您可以在管道中使用任何值,即使该值未被索引。
此示例使用聚合来计算每件商品 10% 的价格折扣,并按从最便宜到最昂贵的顺序对商品进行排序:
127.0.0.1:6379> FT.AGGREGATE itemIdx '*' LOAD 4 name $.price AS originalPrice APPLY '@originalPrice - (@originalPrice * 0.10)' AS salePrice SORTBY 2 @salePrice ASC
1) "2"
2) 1) "name"
2) "Wireless earbuds"
3) "originalPrice"
4) "64.99"
5) "salePrice"
6) "58.491"
3) 1) "name"
2) "Noise-cancelling Bluetooth headphones"
3) "originalPrice"
4) "99.98"
5) "salePrice"
6) "89.982"
索引缺失值或空值
INDEXMISSING从 v2.10 开始,您可以使用选项与查询函数 withFT.CREATE结合使用来搜索缺失的属性,即给定文档中不存在的属性。您还可以使用选项 with搜索没有值(即空)的现有属性。两种查询类型都需要 DIALECT 2。示例如下:ismissingFT.SEARCHINDEXEMPTYFT.CREATE
JSON.SET key:1 $ '{"propA": "foo"}'
JSON.SET key:2 $ '{"propA": "bar", "propB":"abc"}'
FT.CREATE idx ON JSON PREFIX 1 key: SCHEMA $.propA AS propA TAG $.propB AS propB TAG INDEXMISSING
> FT.SEARCH idx 'ismissing(@propB)' DIALECT 2
1) "1"
2) "key:1"
3) 1) "$"
2) "{\"propA\":\"foo\"}"
JSON.SET key:1 $ '{"propA": "foo", "propB":""}'
JSON.SET key:2 $ '{"propA": "bar", "propB":"abc"}'
FT.CREATE idx ON JSON PREFIX 1 key: SCHEMA $.propA AS propA TAG $.propB AS propB TAG INDEXEMPTY
> FT.SEARCH idx '@propB:{""}' DIALECT 2
1) "1"
2) "key:1"
3) 1) "$"
2) "{\"propA\":\"foo\",\"propB\":\"\"}"
索引限制
架构映射
在创建索引时,需要将JSON元素映射到SCHEMA字段,如下所示:
- 字符串为
TEXT、TAG或GEO。 - 数字为
NUMERIC。 - 布尔值为
TAG。 - JSON 数组
- 字符串数组为
TAG或TEXT。 - 数字数组为
NUMERIC或VECTOR。 - 地理坐标数组为
GEO。 null此类数组中的值将被忽略。
- 字符串数组为
- 您无法为 JSON 对象编制索引。请将各个元素作为单独的属性进行编制索引。
null值将被忽略。
可排序标签
如果您为 JSON 文档创建索引,并且 JSONPath 指向一个数组或多个值,则排序只会考虑第一个值。