全文搜索
执行全文搜索
全文搜索可以在较大的文本中查找单词或短语。您可以在特定的文本字段中搜索,也可以在所有文本字段中搜索。
本文提供了最相关的全文搜索功能的良好概述。请在参考文档中找到所有全文搜索功能的更多详细信息。
本文中的示例使用具有以下字段的模式:
字段名称 | 字段类型 |
---|---|
brand |
TEXT |
model |
TEXT |
description |
TEXT |
单个词
要在所有文本字段中搜索一个词(或词干),您可以构建以下简单查询:
FT.SEARCH index "word"
与其在所有文本字段中搜索,您可能希望将搜索限制在特定的文本字段中。
FT.SEARCH index "@field: word"
在自然语言中非常常见的词,例如英语中的the
或a
,不会被索引,也不会返回搜索结果。您可以在停用词文章中找到更多详细信息。
以下示例搜索描述中包含“kids”一词的所有自行车:
FT.SEARCH idx:bicycle "@description: kids"
Are you tired of using redis-cli? Try Redis Insight - the developer GUI for Redis.
import json
import sys
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query
r = redis.Redis(decode_responses=True)
# create index
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)
# load data
with open("data/query_em.json") as f:
bicycles = json.load(f)
pipeline = r.pipeline(transaction=False)
for bid, bicycle in enumerate(bicycles):
pipeline.json().set(f'bicycle:{bid}', Path.root_path(), bicycle)
pipeline.execute()
res = index.search(Query("@description: kids"))
print(res.total)
# >>> 2
res = index.search(Query("@model: ka*"))
print(res.total)
# >>> 1
res = index.search(Query("@brand: *bikes"))
print(res.total)
# >>> 2
res = index.search(Query("%optamized%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
res = index.search(Query("%%optamised%%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
import assert from 'node:assert';
import fs from 'node:fs';
import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps} from 'redis';
const client = createClient();
await client.connect().catch(console.error);
// create index
await client.ft.create('idx:bicycle', {
'$.model': {
type: SchemaFieldTypes.TEXT,
AS: 'model'
},
'$.brand': {
type: SchemaFieldTypes.TEXT,
AS: 'brand'
},
'$.description': {
type: SchemaFieldTypes.TEXT,
AS: 'description'
}
}, {
ON: 'JSON',
PREFIX: 'bicycle:'
})
// load data
const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8'));
await Promise.all(
bicycles.map((bicycle, bid) => {
return client.json.set(`bicycle:${bid}`, '$', bicycle);
})
);
const res1 = await client.ft.search('idx:bicycle', '@description: kids');
console.log(res1.total); // >>> 2
const res2 = await client.ft.search('idx:bicycle', '@model: ka*');
console.log(res2.total); // >>> 1
const res3 = await client.ft.search('idx:bicycle', '@brand: *bikes');
console.log(res3.total); // >>> 2
const res4 = await client.ft.search('idx:bicycle', '%optamized%');
console.log(res4); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
const res5 = await client.ft.search('idx:bicycle', '%%optamised%%');
console.log(res5); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
import java.util.List;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.*;
import redis.clients.jedis.search.schemafields.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.json.Path2;
public class QueryFtExample {
public void run() {
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);
String[] bicycleJsons = new String[] {
" {"
+ " \"pickup_zone\": \"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, "
+ "-74.0610 40.6678, -74.0610 40.7578))\","
+ " \"store_location\": \"-74.0060,40.7128\","
+ " \"brand\": \"Velorim\","
+ " \"model\": \"Jigger\","
+ " \"price\": 270,"
+ " \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! "
+ "This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger "
+ "is the vehicle of choice for the rare tenacious little rider raring to go.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, "
+ "-118.2887 33.9872, -118.2887 34.0972))\","
+ " \"store_location\": \"-118.2437,34.0522\","
+ " \"brand\": \"Bicyk\","
+ " \"model\": \"Hillcraft\","
+ " \"price\": 1200,"
+ " \"description\": \"Kids want to ride with as little weight as possible. Especially "
+ "on an incline! They may be at the age when a 27.5'' wheel bike is just too clumsy coming "
+ "off a 24'' bike. The Hillcraft 26 is just the solution they need!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, "
+ "-87.6848 41.8231, -87.6848 41.9331))\","
+ " \"store_location\": \"-87.6298,41.8781\","
+ " \"brand\": \"Nord\","
+ " \"model\": \"Chook air 5\","
+ " \"price\": 815,"
+ " \"description\": \"The Chook Air 5 gives kids aged six years and older a durable "
+ "and uberlight mountain bike for their first experience on tracks and easy cruising through "
+ "forests and fields. The lower top tube makes it easy to mount and dismount in any "
+ "situation, giving your kids greater safety on the trails.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, "
+ "-80.2433 25.6967, -80.2433 25.8067))\","
+ " \"store_location\": \"-80.1918,25.7617\","
+ " \"brand\": \"Eva\","
+ " \"model\": \"Eva 291\","
+ " \"price\": 3400,"
+ " \"description\": \"The sister company to Nord, Eva launched in 2005 as the first "
+ "and only women-dedicated bicycle brand. Designed by women for women, allEva bikes "
+ "are optimized for the feminine physique using analytics from a body metrics database. "
+ "If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This "
+ "full-suspension, cross-country ride has been designed for velocity. The 291 has "
+ "100mm of front and rear travel, a superlight aluminum frame and fast-rolling "
+ "29-inch wheels. Yippee!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-122.4644 37.8199, -122.3544 37.8199, -122.3544 37.7099, "
+ "-122.4644 37.7099, -122.4644 37.8199))\","
+ " \"store_location\": \"-122.4194,37.7749\","
+ " \"brand\": \"Noka Bikes\","
+ " \"model\": \"Kahuna\","
+ " \"price\": 3200,"
+ " \"description\": \"Whether you want to try your hand at XC racing or are looking "
+ "for a lively trail bike that's just as inspiring on the climbs as it is over rougher "
+ "ground, the Wilder is one heck of a bike built specifically for short women. Both the "
+ "frames and components have been tweaked to include a women’s saddle, different bars "
+ "and unique colourway.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-0.1778 51.5524, 0.0822 51.5524, 0.0822 51.4024, "
+ "-0.1778 51.4024, -0.1778 51.5524))\","
+ " \"store_location\": \"-0.1278,51.5074\","
+ " \"brand\": \"Breakout\","
+ " \"model\": \"XBN 2.1 Alloy\","
+ " \"price\": 810,"
+ " \"description\": \"The XBN 2.1 Alloy is our entry-level road bike – but that’s "
+ "not to say that it’s a basic machine. With an internal weld aluminium frame, a full "
+ "carbon fork, and the slick-shifting Claris gears from Shimano’s, this is a bike which "
+ "doesn’t break the bank and delivers craved performance.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((2.1767 48.9016, 2.5267 48.9016, 2.5267 48.5516, "
+ "2.1767 48.5516, 2.1767 48.9016))\","
+ " \"store_location\": \"2.3522,48.8566\","
+ " \"brand\": \"ScramBikes\","
+ " \"model\": \"WattBike\","
+ " \"price\": 2300,"
+ " \"description\": \"The WattBike is the best e-bike for people who still "
+ "feel young at heart. It has a Bafang 1000W mid-drive system and a 48V 17.5AH "
+ "Samsung Lithium-Ion battery, allowing you to ride for more than 60 miles on one "
+ "charge. It’s great for tackling hilly terrain or if you just fancy a more "
+ "leisurely ride. With three working modes, you can choose between E-bike, "
+ "assisted bicycle, and normal bike modes.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((13.3260 52.5700, 13.6550 52.5700, 13.6550 52.2700, "
+ "13.3260 52.2700, 13.3260 52.5700))\","
+ " \"store_location\": \"13.4050,52.5200\","
+ " \"brand\": \"Peaknetic\","
+ " \"model\": \"Secto\","
+ " \"price\": 430,"
+ " \"description\": \"If you struggle with stiff fingers or a kinked neck or "
+ "back after a few minutes on the road, this lightweight, aluminum bike alleviates "
+ "those issues and allows you to enjoy the ride. From the ergonomic grips to the "
+ "lumbar-supporting seat position, the Roll Low-Entry offers incredible comfort. "
+ "The rear-inclined seat tube facilitates stability by allowing you to put a foot "
+ "on the ground to balance at a stop, and the low step-over frame makes it "
+ "accessible for all ability and mobility levels. The saddle is very soft, with "
+ "a wide back to support your hip joints and a cutout in the center to redistribute "
+ "that pressure. Rim brakes deliver satisfactory braking control, and the wide tires "
+ "provide a smooth, stable ride on paved roads and gravel. Rack and fender mounts "
+ "facilitate setting up the Roll Low-Entry as your preferred commuter, and the "
+ "BMX-like handlebar offers space for mounting a flashlight, bell, or phone holder.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((1.9450 41.4301, 2.4018 41.4301, 2.4018 41.1987, "
+ "1.9450 41.1987, 1.9450 41.4301))\","
+ " \"store_location\": \"2.1734, 41.3851\","
+ " \"brand\": \"nHill\","
+ " \"model\": \"Summit\","
+ " \"price\": 1200,"
+ " \"description\": \"This budget mountain bike from nHill performs well both "
+ "on bike paths and on the trail. The fork with 100mm of travel absorbs rough "
+ "terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. "
+ "The Shimano Tourney drivetrain offered enough gears for finding a comfortable "
+ "pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. "
+ "Whether you want an affordable bike that you can take to work, but also take "
+ "trail in mountains on the weekends or you’re just after a stable, comfortable "
+ "ride for the bike path, the Summit gives a good value for money.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((12.4464 42.1028, 12.5464 42.1028, "
+ "12.5464 41.7028, 12.4464 41.7028, 12.4464 42.1028))\","
+ " \"store_location\": \"12.4964,41.9028\","
+ " \"model\": \"ThrillCycle\","
+ " \"brand\": \"BikeShind\","
+ " \"price\": 815,"
+ " \"description\": \"An artsy, retro-inspired bicycle that’s as "
+ "functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. "
+ "A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn’t "
+ "suggest taking it to the mountains. Fenders protect you from mud, and a rear "
+ "basket lets you transport groceries, flowers and books. The ThrillCycle comes "
+ "with a limited lifetime warranty, so this little guy will last you long "
+ "past graduation.\","
+ " \"condition\": \"refurbished\""
+ " }"
};
for (int i = 0; i < bicycleJsons.length; i++) {
jedis.jsonSet("bicycle:" + i, Path2.ROOT_PATH, bicycleJsons[i]);
}
SearchResult res1 = jedis.ftSearch("idx:bicycle", "@description: kids");
System.out.println(res1.getTotalResults()); // >>> 2
List<Document> docs1 = res1.getDocuments();
for (int i = 0; i < docs1.size(); i++) {
System.out.println(docs1.get(i).getId());
}
// >>> bicycle:2
// >>> bicycle:1
// Tests for 'ft1' step.
SearchResult res2 = jedis.ftSearch("idx:bicycle", "@model: ka*");
System.out.println(res2.getTotalResults()); // >>> 1
List<Document> docs2 = res2.getDocuments();
for (int i = 0; i < docs2.size(); i++) {
System.out.println(docs2.get(i).getId());
}
// >>> bicycle:4
// Tests for 'ft2' step.
SearchResult res3 = jedis.ftSearch("idx:bicycle", "@brand: *bikes");
System.out.println(res3.getTotalResults()); // >>> 2
List<Document> docs3 = res3.getDocuments();
for (int i = 0; i < docs3.size(); i++) {
System.out.println(docs3.get(i).getId());
}
// >>> bicycle:6
// >>> bicycle:4
// Tests for 'ft3' step.
SearchResult res4 = jedis.ftSearch("idx:bicycle", "%optamized%");
System.out.println(res4.getTotalResults()); // >>> 1
List<Document> docs4 = res4.getDocuments();
for (int i = 0; i < docs4.size(); i++) {
System.out.println(docs4.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft4' step.
SearchResult res5 = jedis.ftSearch("idx:bicycle", "%%optamised%%");
System.out.println(res5.getTotalResults()); // >>> 1
List<Document> docs5 = res5.getDocuments();
for (int i = 0; i < docs5.size(); i++) {
System.out.println(docs5.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft5' step.
jedis.close();
}
}
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NRedisStack.Search.Literals.Enums;
using NRedisStack.Tests;
using StackExchange.Redis;
public class QueryFtExample
{
public void run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
Schema bikeSchema = new Schema()
.AddTextField(new FieldName("$.brand", "brand"))
.AddTextField(new FieldName("$.model", "model"))
.AddTextField(new FieldName("$.description", "description"));
FTCreateParams bikeParams = new FTCreateParams()
.AddPrefix("bicycle:")
.On(IndexDataType.JSON);
db.FT().Create("idx:bicycle", bikeParams, bikeSchema);
var bicycles = new object[]
{
new
{
brand = "Velorim",
model = "Jigger",
price = 270,
description = "Small and powerful, the Jigger is the best ride " +
"for the smallest of tikes! This is the tiniest " +
"kids’ pedal bike on the market available without" +
" a coaster brake, the Jigger is the vehicle of " +
"choice for the rare tenacious little rider " +
"raring to go.",
condition = "used"
},
new
{
brand = "Bicyk",
model = "Hillcraft",
price = 1200,
description = "Kids want to ride with as little weight as possible." +
" Especially on an incline! They may be at the age " +
"when a 27.5 inch wheel bike is just too clumsy coming " +
"off a 24 inch bike. The Hillcraft 26 is just the solution" +
" they need!",
condition = "used",
},
new
{
brand = "Nord",
model = "Chook air 5",
price = 815,
description = "The Chook Air 5 gives kids aged six years and older " +
"a durable and uberlight mountain bike for their first" +
" experience on tracks and easy cruising through forests" +
" and fields. The lower top tube makes it easy to mount" +
" and dismount in any situation, giving your kids greater" +
" safety on the trails.",
condition = "used",
},
new
{
brand = "Eva",
model = "Eva 291",
price = 3400,
description = "The sister company to Nord, Eva launched in 2005 as the" +
" first and only women-dedicated bicycle brand. Designed" +
" by women for women, allEva bikes are optimized for the" +
" feminine physique using analytics from a body metrics" +
" database. If you like 29ers, try the Eva 291. It’s a " +
"brand new bike for 2022.. This full-suspension, " +
"cross-country ride has been designed for velocity. The" +
" 291 has 100mm of front and rear travel, a superlight " +
"aluminum frame and fast-rolling 29-inch wheels. Yippee!",
condition = "used",
},
new
{
brand = "Noka Bikes",
model = "Kahuna",
price = 3200,
description = "Whether you want to try your hand at XC racing or are " +
"looking for a lively trail bike that's just as inspiring" +
" on the climbs as it is over rougher ground, the Wilder" +
" is one heck of a bike built specifically for short women." +
" Both the frames and components have been tweaked to " +
"include a women’s saddle, different bars and unique " +
"colourway.",
condition = "used",
},
new
{
brand = "Breakout",
model = "XBN 2.1 Alloy",
price = 810,
description = "The XBN 2.1 Alloy is our entry-level road bike – but that’s" +
" not to say that it’s a basic machine. With an internal " +
"weld aluminium frame, a full carbon fork, and the slick-shifting" +
" Claris gears from Shimano’s, this is a bike which doesn’t" +
" break the bank and delivers craved performance.",
condition = "new",
},
new
{
brand = "ScramBikes",
model = "WattBike",
price = 2300,
description = "The WattBike is the best e-bike for people who still feel young" +
" at heart. It has a Bafang 1000W mid-drive system and a 48V" +
" 17.5AH Samsung Lithium-Ion battery, allowing you to ride for" +
" more than 60 miles on one charge. It’s great for tackling hilly" +
" terrain or if you just fancy a more leisurely ride. With three" +
" working modes, you can choose between E-bike, assisted bicycle," +
" and normal bike modes.",
condition = "new",
},
new
{
brand = "Peaknetic",
model = "Secto",
price = 430,
description = "If you struggle with stiff fingers or a kinked neck or back after" +
" a few minutes on the road, this lightweight, aluminum bike" +
" alleviates those issues and allows you to enjoy the ride. From" +
" the ergonomic grips to the lumbar-supporting seat position, the" +
" Roll Low-Entry offers incredible comfort. The rear-inclined seat" +
" tube facilitates stability by allowing you to put a foot on the" +
" ground to balance at a stop, and the low step-over frame makes it" +
" accessible for all ability and mobility levels. The saddle is" +
" very soft, with a wide back to support your hip joints and a" +
" cutout in the center to redistribute that pressure. Rim brakes" +
" deliver satisfactory braking control, and the wide tires provide" +
" a smooth, stable ride on paved roads and gravel. Rack and fender" +
" mounts facilitate setting up the Roll Low-Entry as your preferred" +
" commuter, and the BMX-like handlebar offers space for mounting a" +
" flashlight, bell, or phone holder.",
condition = "new",
},
new
{
brand = "nHill",
model = "Summit",
price = 1200,
description = "This budget mountain bike from nHill performs well both on bike" +
" paths and on the trail. The fork with 100mm of travel absorbs" +
" rough terrain. Fat Kenda Booster tires give you grip in corners" +
" and on wet trails. The Shimano Tourney drivetrain offered enough" +
" gears for finding a comfortable pace to ride uphill, and the" +
" Tektro hydraulic disc brakes break smoothly. Whether you want an" +
" affordable bike that you can take to work, but also take trail in" +
" mountains on the weekends or you’re just after a stable," +
" comfortable ride for the bike path, the Summit gives a good value" +
" for money.",
condition = "new",
},
new
{
model = "ThrillCycle",
brand = "BikeShind",
price = 815,
description = "An artsy, retro-inspired bicycle that’s as functional as it is" +
" pretty: The ThrillCycle steel frame offers a smooth ride. A" +
" 9-speed drivetrain has enough gears for coasting in the city, but" +
" we wouldn’t suggest taking it to the mountains. Fenders protect" +
" you from mud, and a rear basket lets you transport groceries," +
" flowers and books. The ThrillCycle comes with a limited lifetime" +
" warranty, so this little guy will last you long past graduation.",
condition = "refurbished",
},
};
for (var i = 0; i < bicycles.Length; i++)
{
db.JSON().Set($"bicycle:{i}", "$", bicycles[i]);
}
SearchResult res1 = db.FT().Search(
"idx:bicycle",
new Query("@description: kids")
);
Console.WriteLine(res1); // >>> 2
// Tests for 'ft1' step.
SearchResult res2 = db.FT().Search(
"idx:bicycle",
new Query("@model: ka*")
);
Console.WriteLine(res2.TotalResults); // >>> 1
// Tests for 'ft2' step.
SearchResult res3 = db.FT().Search(
"idx:bicycle",
new Query("@brand: *bikes")
);
Console.WriteLine(res3.TotalResults); // >>> 2
// Tests for 'ft3' step.
SearchResult res4 = db.FT().Search(
"idx:bicycle",
new Query("%optamized%")
);
Console.WriteLine(res4.TotalResults); // >>> 1
// Tests for 'ft4' step.
SearchResult res5 = db.FT().Search(
"idx:bicycle",
new Query("%%optamised%%")
);
Console.WriteLine(res5.TotalResults); // >>> 1
// Tests for 'ft5' step.
}
}
短语
短语是一个句子、句子片段或一小群单词。您可以在精确匹配文章中找到关于如何查找精确短语的更多详细信息。
单词前缀
你也可以搜索匹配给定前缀的单词。
FT.SEARCH index "prefix*"
FT.SEARCH index "@field: prefix*"
重要提示:
前缀需要至少两个字符长。以下是一个示例,向您展示如何搜索品牌以'ka'开头的自行车:
FT.SEARCH idx:bicycle "@model: ka*"
Are you tired of using redis-cli? Try Redis Insight - the developer GUI for Redis.
import json
import sys
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query
r = redis.Redis(decode_responses=True)
# create index
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)
# load data
with open("data/query_em.json") as f:
bicycles = json.load(f)
pipeline = r.pipeline(transaction=False)
for bid, bicycle in enumerate(bicycles):
pipeline.json().set(f'bicycle:{bid}', Path.root_path(), bicycle)
pipeline.execute()
res = index.search(Query("@description: kids"))
print(res.total)
# >>> 2
res = index.search(Query("@model: ka*"))
print(res.total)
# >>> 1
res = index.search(Query("@brand: *bikes"))
print(res.total)
# >>> 2
res = index.search(Query("%optamized%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
res = index.search(Query("%%optamised%%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
import assert from 'node:assert';
import fs from 'node:fs';
import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps} from 'redis';
const client = createClient();
await client.connect().catch(console.error);
// create index
await client.ft.create('idx:bicycle', {
'$.model': {
type: SchemaFieldTypes.TEXT,
AS: 'model'
},
'$.brand': {
type: SchemaFieldTypes.TEXT,
AS: 'brand'
},
'$.description': {
type: SchemaFieldTypes.TEXT,
AS: 'description'
}
}, {
ON: 'JSON',
PREFIX: 'bicycle:'
})
// load data
const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8'));
await Promise.all(
bicycles.map((bicycle, bid) => {
return client.json.set(`bicycle:${bid}`, '$', bicycle);
})
);
const res1 = await client.ft.search('idx:bicycle', '@description: kids');
console.log(res1.total); // >>> 2
const res2 = await client.ft.search('idx:bicycle', '@model: ka*');
console.log(res2.total); // >>> 1
const res3 = await client.ft.search('idx:bicycle', '@brand: *bikes');
console.log(res3.total); // >>> 2
const res4 = await client.ft.search('idx:bicycle', '%optamized%');
console.log(res4); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
const res5 = await client.ft.search('idx:bicycle', '%%optamised%%');
console.log(res5); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
import java.util.List;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.*;
import redis.clients.jedis.search.schemafields.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.json.Path2;
public class QueryFtExample {
public void run() {
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);
String[] bicycleJsons = new String[] {
" {"
+ " \"pickup_zone\": \"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, "
+ "-74.0610 40.6678, -74.0610 40.7578))\","
+ " \"store_location\": \"-74.0060,40.7128\","
+ " \"brand\": \"Velorim\","
+ " \"model\": \"Jigger\","
+ " \"price\": 270,"
+ " \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! "
+ "This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger "
+ "is the vehicle of choice for the rare tenacious little rider raring to go.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, "
+ "-118.2887 33.9872, -118.2887 34.0972))\","
+ " \"store_location\": \"-118.2437,34.0522\","
+ " \"brand\": \"Bicyk\","
+ " \"model\": \"Hillcraft\","
+ " \"price\": 1200,"
+ " \"description\": \"Kids want to ride with as little weight as possible. Especially "
+ "on an incline! They may be at the age when a 27.5'' wheel bike is just too clumsy coming "
+ "off a 24'' bike. The Hillcraft 26 is just the solution they need!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, "
+ "-87.6848 41.8231, -87.6848 41.9331))\","
+ " \"store_location\": \"-87.6298,41.8781\","
+ " \"brand\": \"Nord\","
+ " \"model\": \"Chook air 5\","
+ " \"price\": 815,"
+ " \"description\": \"The Chook Air 5 gives kids aged six years and older a durable "
+ "and uberlight mountain bike for their first experience on tracks and easy cruising through "
+ "forests and fields. The lower top tube makes it easy to mount and dismount in any "
+ "situation, giving your kids greater safety on the trails.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, "
+ "-80.2433 25.6967, -80.2433 25.8067))\","
+ " \"store_location\": \"-80.1918,25.7617\","
+ " \"brand\": \"Eva\","
+ " \"model\": \"Eva 291\","
+ " \"price\": 3400,"
+ " \"description\": \"The sister company to Nord, Eva launched in 2005 as the first "
+ "and only women-dedicated bicycle brand. Designed by women for women, allEva bikes "
+ "are optimized for the feminine physique using analytics from a body metrics database. "
+ "If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This "
+ "full-suspension, cross-country ride has been designed for velocity. The 291 has "
+ "100mm of front and rear travel, a superlight aluminum frame and fast-rolling "
+ "29-inch wheels. Yippee!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-122.4644 37.8199, -122.3544 37.8199, -122.3544 37.7099, "
+ "-122.4644 37.7099, -122.4644 37.8199))\","
+ " \"store_location\": \"-122.4194,37.7749\","
+ " \"brand\": \"Noka Bikes\","
+ " \"model\": \"Kahuna\","
+ " \"price\": 3200,"
+ " \"description\": \"Whether you want to try your hand at XC racing or are looking "
+ "for a lively trail bike that's just as inspiring on the climbs as it is over rougher "
+ "ground, the Wilder is one heck of a bike built specifically for short women. Both the "
+ "frames and components have been tweaked to include a women’s saddle, different bars "
+ "and unique colourway.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-0.1778 51.5524, 0.0822 51.5524, 0.0822 51.4024, "
+ "-0.1778 51.4024, -0.1778 51.5524))\","
+ " \"store_location\": \"-0.1278,51.5074\","
+ " \"brand\": \"Breakout\","
+ " \"model\": \"XBN 2.1 Alloy\","
+ " \"price\": 810,"
+ " \"description\": \"The XBN 2.1 Alloy is our entry-level road bike – but that’s "
+ "not to say that it’s a basic machine. With an internal weld aluminium frame, a full "
+ "carbon fork, and the slick-shifting Claris gears from Shimano’s, this is a bike which "
+ "doesn’t break the bank and delivers craved performance.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((2.1767 48.9016, 2.5267 48.9016, 2.5267 48.5516, "
+ "2.1767 48.5516, 2.1767 48.9016))\","
+ " \"store_location\": \"2.3522,48.8566\","
+ " \"brand\": \"ScramBikes\","
+ " \"model\": \"WattBike\","
+ " \"price\": 2300,"
+ " \"description\": \"The WattBike is the best e-bike for people who still "
+ "feel young at heart. It has a Bafang 1000W mid-drive system and a 48V 17.5AH "
+ "Samsung Lithium-Ion battery, allowing you to ride for more than 60 miles on one "
+ "charge. It’s great for tackling hilly terrain or if you just fancy a more "
+ "leisurely ride. With three working modes, you can choose between E-bike, "
+ "assisted bicycle, and normal bike modes.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((13.3260 52.5700, 13.6550 52.5700, 13.6550 52.2700, "
+ "13.3260 52.2700, 13.3260 52.5700))\","
+ " \"store_location\": \"13.4050,52.5200\","
+ " \"brand\": \"Peaknetic\","
+ " \"model\": \"Secto\","
+ " \"price\": 430,"
+ " \"description\": \"If you struggle with stiff fingers or a kinked neck or "
+ "back after a few minutes on the road, this lightweight, aluminum bike alleviates "
+ "those issues and allows you to enjoy the ride. From the ergonomic grips to the "
+ "lumbar-supporting seat position, the Roll Low-Entry offers incredible comfort. "
+ "The rear-inclined seat tube facilitates stability by allowing you to put a foot "
+ "on the ground to balance at a stop, and the low step-over frame makes it "
+ "accessible for all ability and mobility levels. The saddle is very soft, with "
+ "a wide back to support your hip joints and a cutout in the center to redistribute "
+ "that pressure. Rim brakes deliver satisfactory braking control, and the wide tires "
+ "provide a smooth, stable ride on paved roads and gravel. Rack and fender mounts "
+ "facilitate setting up the Roll Low-Entry as your preferred commuter, and the "
+ "BMX-like handlebar offers space for mounting a flashlight, bell, or phone holder.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((1.9450 41.4301, 2.4018 41.4301, 2.4018 41.1987, "
+ "1.9450 41.1987, 1.9450 41.4301))\","
+ " \"store_location\": \"2.1734, 41.3851\","
+ " \"brand\": \"nHill\","
+ " \"model\": \"Summit\","
+ " \"price\": 1200,"
+ " \"description\": \"This budget mountain bike from nHill performs well both "
+ "on bike paths and on the trail. The fork with 100mm of travel absorbs rough "
+ "terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. "
+ "The Shimano Tourney drivetrain offered enough gears for finding a comfortable "
+ "pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. "
+ "Whether you want an affordable bike that you can take to work, but also take "
+ "trail in mountains on the weekends or you’re just after a stable, comfortable "
+ "ride for the bike path, the Summit gives a good value for money.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((12.4464 42.1028, 12.5464 42.1028, "
+ "12.5464 41.7028, 12.4464 41.7028, 12.4464 42.1028))\","
+ " \"store_location\": \"12.4964,41.9028\","
+ " \"model\": \"ThrillCycle\","
+ " \"brand\": \"BikeShind\","
+ " \"price\": 815,"
+ " \"description\": \"An artsy, retro-inspired bicycle that’s as "
+ "functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. "
+ "A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn’t "
+ "suggest taking it to the mountains. Fenders protect you from mud, and a rear "
+ "basket lets you transport groceries, flowers and books. The ThrillCycle comes "
+ "with a limited lifetime warranty, so this little guy will last you long "
+ "past graduation.\","
+ " \"condition\": \"refurbished\""
+ " }"
};
for (int i = 0; i < bicycleJsons.length; i++) {
jedis.jsonSet("bicycle:" + i, Path2.ROOT_PATH, bicycleJsons[i]);
}
SearchResult res1 = jedis.ftSearch("idx:bicycle", "@description: kids");
System.out.println(res1.getTotalResults()); // >>> 2
List<Document> docs1 = res1.getDocuments();
for (int i = 0; i < docs1.size(); i++) {
System.out.println(docs1.get(i).getId());
}
// >>> bicycle:2
// >>> bicycle:1
// Tests for 'ft1' step.
SearchResult res2 = jedis.ftSearch("idx:bicycle", "@model: ka*");
System.out.println(res2.getTotalResults()); // >>> 1
List<Document> docs2 = res2.getDocuments();
for (int i = 0; i < docs2.size(); i++) {
System.out.println(docs2.get(i).getId());
}
// >>> bicycle:4
// Tests for 'ft2' step.
SearchResult res3 = jedis.ftSearch("idx:bicycle", "@brand: *bikes");
System.out.println(res3.getTotalResults()); // >>> 2
List<Document> docs3 = res3.getDocuments();
for (int i = 0; i < docs3.size(); i++) {
System.out.println(docs3.get(i).getId());
}
// >>> bicycle:6
// >>> bicycle:4
// Tests for 'ft3' step.
SearchResult res4 = jedis.ftSearch("idx:bicycle", "%optamized%");
System.out.println(res4.getTotalResults()); // >>> 1
List<Document> docs4 = res4.getDocuments();
for (int i = 0; i < docs4.size(); i++) {
System.out.println(docs4.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft4' step.
SearchResult res5 = jedis.ftSearch("idx:bicycle", "%%optamised%%");
System.out.println(res5.getTotalResults()); // >>> 1
List<Document> docs5 = res5.getDocuments();
for (int i = 0; i < docs5.size(); i++) {
System.out.println(docs5.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft5' step.
jedis.close();
}
}
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NRedisStack.Search.Literals.Enums;
using NRedisStack.Tests;
using StackExchange.Redis;
public class QueryFtExample
{
public void run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
Schema bikeSchema = new Schema()
.AddTextField(new FieldName("$.brand", "brand"))
.AddTextField(new FieldName("$.model", "model"))
.AddTextField(new FieldName("$.description", "description"));
FTCreateParams bikeParams = new FTCreateParams()
.AddPrefix("bicycle:")
.On(IndexDataType.JSON);
db.FT().Create("idx:bicycle", bikeParams, bikeSchema);
var bicycles = new object[]
{
new
{
brand = "Velorim",
model = "Jigger",
price = 270,
description = "Small and powerful, the Jigger is the best ride " +
"for the smallest of tikes! This is the tiniest " +
"kids’ pedal bike on the market available without" +
" a coaster brake, the Jigger is the vehicle of " +
"choice for the rare tenacious little rider " +
"raring to go.",
condition = "used"
},
new
{
brand = "Bicyk",
model = "Hillcraft",
price = 1200,
description = "Kids want to ride with as little weight as possible." +
" Especially on an incline! They may be at the age " +
"when a 27.5 inch wheel bike is just too clumsy coming " +
"off a 24 inch bike. The Hillcraft 26 is just the solution" +
" they need!",
condition = "used",
},
new
{
brand = "Nord",
model = "Chook air 5",
price = 815,
description = "The Chook Air 5 gives kids aged six years and older " +
"a durable and uberlight mountain bike for their first" +
" experience on tracks and easy cruising through forests" +
" and fields. The lower top tube makes it easy to mount" +
" and dismount in any situation, giving your kids greater" +
" safety on the trails.",
condition = "used",
},
new
{
brand = "Eva",
model = "Eva 291",
price = 3400,
description = "The sister company to Nord, Eva launched in 2005 as the" +
" first and only women-dedicated bicycle brand. Designed" +
" by women for women, allEva bikes are optimized for the" +
" feminine physique using analytics from a body metrics" +
" database. If you like 29ers, try the Eva 291. It’s a " +
"brand new bike for 2022.. This full-suspension, " +
"cross-country ride has been designed for velocity. The" +
" 291 has 100mm of front and rear travel, a superlight " +
"aluminum frame and fast-rolling 29-inch wheels. Yippee!",
condition = "used",
},
new
{
brand = "Noka Bikes",
model = "Kahuna",
price = 3200,
description = "Whether you want to try your hand at XC racing or are " +
"looking for a lively trail bike that's just as inspiring" +
" on the climbs as it is over rougher ground, the Wilder" +
" is one heck of a bike built specifically for short women." +
" Both the frames and components have been tweaked to " +
"include a women’s saddle, different bars and unique " +
"colourway.",
condition = "used",
},
new
{
brand = "Breakout",
model = "XBN 2.1 Alloy",
price = 810,
description = "The XBN 2.1 Alloy is our entry-level road bike – but that’s" +
" not to say that it’s a basic machine. With an internal " +
"weld aluminium frame, a full carbon fork, and the slick-shifting" +
" Claris gears from Shimano’s, this is a bike which doesn’t" +
" break the bank and delivers craved performance.",
condition = "new",
},
new
{
brand = "ScramBikes",
model = "WattBike",
price = 2300,
description = "The WattBike is the best e-bike for people who still feel young" +
" at heart. It has a Bafang 1000W mid-drive system and a 48V" +
" 17.5AH Samsung Lithium-Ion battery, allowing you to ride for" +
" more than 60 miles on one charge. It’s great for tackling hilly" +
" terrain or if you just fancy a more leisurely ride. With three" +
" working modes, you can choose between E-bike, assisted bicycle," +
" and normal bike modes.",
condition = "new",
},
new
{
brand = "Peaknetic",
model = "Secto",
price = 430,
description = "If you struggle with stiff fingers or a kinked neck or back after" +
" a few minutes on the road, this lightweight, aluminum bike" +
" alleviates those issues and allows you to enjoy the ride. From" +
" the ergonomic grips to the lumbar-supporting seat position, the" +
" Roll Low-Entry offers incredible comfort. The rear-inclined seat" +
" tube facilitates stability by allowing you to put a foot on the" +
" ground to balance at a stop, and the low step-over frame makes it" +
" accessible for all ability and mobility levels. The saddle is" +
" very soft, with a wide back to support your hip joints and a" +
" cutout in the center to redistribute that pressure. Rim brakes" +
" deliver satisfactory braking control, and the wide tires provide" +
" a smooth, stable ride on paved roads and gravel. Rack and fender" +
" mounts facilitate setting up the Roll Low-Entry as your preferred" +
" commuter, and the BMX-like handlebar offers space for mounting a" +
" flashlight, bell, or phone holder.",
condition = "new",
},
new
{
brand = "nHill",
model = "Summit",
price = 1200,
description = "This budget mountain bike from nHill performs well both on bike" +
" paths and on the trail. The fork with 100mm of travel absorbs" +
" rough terrain. Fat Kenda Booster tires give you grip in corners" +
" and on wet trails. The Shimano Tourney drivetrain offered enough" +
" gears for finding a comfortable pace to ride uphill, and the" +
" Tektro hydraulic disc brakes break smoothly. Whether you want an" +
" affordable bike that you can take to work, but also take trail in" +
" mountains on the weekends or you’re just after a stable," +
" comfortable ride for the bike path, the Summit gives a good value" +
" for money.",
condition = "new",
},
new
{
model = "ThrillCycle",
brand = "BikeShind",
price = 815,
description = "An artsy, retro-inspired bicycle that’s as functional as it is" +
" pretty: The ThrillCycle steel frame offers a smooth ride. A" +
" 9-speed drivetrain has enough gears for coasting in the city, but" +
" we wouldn’t suggest taking it to the mountains. Fenders protect" +
" you from mud, and a rear basket lets you transport groceries," +
" flowers and books. The ThrillCycle comes with a limited lifetime" +
" warranty, so this little guy will last you long past graduation.",
condition = "refurbished",
},
};
for (var i = 0; i < bicycles.Length; i++)
{
db.JSON().Set($"bicycle:{i}", "$", bicycles[i]);
}
SearchResult res1 = db.FT().Search(
"idx:bicycle",
new Query("@description: kids")
);
Console.WriteLine(res1); // >>> 2
// Tests for 'ft1' step.
SearchResult res2 = db.FT().Search(
"idx:bicycle",
new Query("@model: ka*")
);
Console.WriteLine(res2.TotalResults); // >>> 1
// Tests for 'ft2' step.
SearchResult res3 = db.FT().Search(
"idx:bicycle",
new Query("@brand: *bikes")
);
Console.WriteLine(res3.TotalResults); // >>> 2
// Tests for 'ft3' step.
SearchResult res4 = db.FT().Search(
"idx:bicycle",
new Query("%optamized%")
);
Console.WriteLine(res4.TotalResults); // >>> 1
// Tests for 'ft4' step.
SearchResult res5 = db.FT().Search(
"idx:bicycle",
new Query("%%optamised%%")
);
Console.WriteLine(res5.TotalResults); // >>> 1
// Tests for 'ft5' step.
}
}
单词后缀
与前缀类似,也可以搜索具有相同后缀的单词。
FT.SEARCH index "*suffix"
您还可以在查询表达式中结合使用前缀和后缀搜索。
FT.SEARCH index "*infix*"
以下是一个查找所有以“bikes”结尾的品牌的示例:
FT.SEARCH idx:bicycle "@brand:*bikes"
Are you tired of using redis-cli? Try Redis Insight - the developer GUI for Redis.
import json
import sys
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query
r = redis.Redis(decode_responses=True)
# create index
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)
# load data
with open("data/query_em.json") as f:
bicycles = json.load(f)
pipeline = r.pipeline(transaction=False)
for bid, bicycle in enumerate(bicycles):
pipeline.json().set(f'bicycle:{bid}', Path.root_path(), bicycle)
pipeline.execute()
res = index.search(Query("@description: kids"))
print(res.total)
# >>> 2
res = index.search(Query("@model: ka*"))
print(res.total)
# >>> 1
res = index.search(Query("@brand: *bikes"))
print(res.total)
# >>> 2
res = index.search(Query("%optamized%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
res = index.search(Query("%%optamised%%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
import assert from 'node:assert';
import fs from 'node:fs';
import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps} from 'redis';
const client = createClient();
await client.connect().catch(console.error);
// create index
await client.ft.create('idx:bicycle', {
'$.model': {
type: SchemaFieldTypes.TEXT,
AS: 'model'
},
'$.brand': {
type: SchemaFieldTypes.TEXT,
AS: 'brand'
},
'$.description': {
type: SchemaFieldTypes.TEXT,
AS: 'description'
}
}, {
ON: 'JSON',
PREFIX: 'bicycle:'
})
// load data
const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8'));
await Promise.all(
bicycles.map((bicycle, bid) => {
return client.json.set(`bicycle:${bid}`, '$', bicycle);
})
);
const res1 = await client.ft.search('idx:bicycle', '@description: kids');
console.log(res1.total); // >>> 2
const res2 = await client.ft.search('idx:bicycle', '@model: ka*');
console.log(res2.total); // >>> 1
const res3 = await client.ft.search('idx:bicycle', '@brand: *bikes');
console.log(res3.total); // >>> 2
const res4 = await client.ft.search('idx:bicycle', '%optamized%');
console.log(res4); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
const res5 = await client.ft.search('idx:bicycle', '%%optamised%%');
console.log(res5); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
import java.util.List;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.*;
import redis.clients.jedis.search.schemafields.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.json.Path2;
public class QueryFtExample {
public void run() {
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);
String[] bicycleJsons = new String[] {
" {"
+ " \"pickup_zone\": \"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, "
+ "-74.0610 40.6678, -74.0610 40.7578))\","
+ " \"store_location\": \"-74.0060,40.7128\","
+ " \"brand\": \"Velorim\","
+ " \"model\": \"Jigger\","
+ " \"price\": 270,"
+ " \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! "
+ "This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger "
+ "is the vehicle of choice for the rare tenacious little rider raring to go.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, "
+ "-118.2887 33.9872, -118.2887 34.0972))\","
+ " \"store_location\": \"-118.2437,34.0522\","
+ " \"brand\": \"Bicyk\","
+ " \"model\": \"Hillcraft\","
+ " \"price\": 1200,"
+ " \"description\": \"Kids want to ride with as little weight as possible. Especially "
+ "on an incline! They may be at the age when a 27.5'' wheel bike is just too clumsy coming "
+ "off a 24'' bike. The Hillcraft 26 is just the solution they need!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, "
+ "-87.6848 41.8231, -87.6848 41.9331))\","
+ " \"store_location\": \"-87.6298,41.8781\","
+ " \"brand\": \"Nord\","
+ " \"model\": \"Chook air 5\","
+ " \"price\": 815,"
+ " \"description\": \"The Chook Air 5 gives kids aged six years and older a durable "
+ "and uberlight mountain bike for their first experience on tracks and easy cruising through "
+ "forests and fields. The lower top tube makes it easy to mount and dismount in any "
+ "situation, giving your kids greater safety on the trails.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, "
+ "-80.2433 25.6967, -80.2433 25.8067))\","
+ " \"store_location\": \"-80.1918,25.7617\","
+ " \"brand\": \"Eva\","
+ " \"model\": \"Eva 291\","
+ " \"price\": 3400,"
+ " \"description\": \"The sister company to Nord, Eva launched in 2005 as the first "
+ "and only women-dedicated bicycle brand. Designed by women for women, allEva bikes "
+ "are optimized for the feminine physique using analytics from a body metrics database. "
+ "If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This "
+ "full-suspension, cross-country ride has been designed for velocity. The 291 has "
+ "100mm of front and rear travel, a superlight aluminum frame and fast-rolling "
+ "29-inch wheels. Yippee!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-122.4644 37.8199, -122.3544 37.8199, -122.3544 37.7099, "
+ "-122.4644 37.7099, -122.4644 37.8199))\","
+ " \"store_location\": \"-122.4194,37.7749\","
+ " \"brand\": \"Noka Bikes\","
+ " \"model\": \"Kahuna\","
+ " \"price\": 3200,"
+ " \"description\": \"Whether you want to try your hand at XC racing or are looking "
+ "for a lively trail bike that's just as inspiring on the climbs as it is over rougher "
+ "ground, the Wilder is one heck of a bike built specifically for short women. Both the "
+ "frames and components have been tweaked to include a women’s saddle, different bars "
+ "and unique colourway.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-0.1778 51.5524, 0.0822 51.5524, 0.0822 51.4024, "
+ "-0.1778 51.4024, -0.1778 51.5524))\","
+ " \"store_location\": \"-0.1278,51.5074\","
+ " \"brand\": \"Breakout\","
+ " \"model\": \"XBN 2.1 Alloy\","
+ " \"price\": 810,"
+ " \"description\": \"The XBN 2.1 Alloy is our entry-level road bike – but that’s "
+ "not to say that it’s a basic machine. With an internal weld aluminium frame, a full "
+ "carbon fork, and the slick-shifting Claris gears from Shimano’s, this is a bike which "
+ "doesn’t break the bank and delivers craved performance.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((2.1767 48.9016, 2.5267 48.9016, 2.5267 48.5516, "
+ "2.1767 48.5516, 2.1767 48.9016))\","
+ " \"store_location\": \"2.3522,48.8566\","
+ " \"brand\": \"ScramBikes\","
+ " \"model\": \"WattBike\","
+ " \"price\": 2300,"
+ " \"description\": \"The WattBike is the best e-bike for people who still "
+ "feel young at heart. It has a Bafang 1000W mid-drive system and a 48V 17.5AH "
+ "Samsung Lithium-Ion battery, allowing you to ride for more than 60 miles on one "
+ "charge. It’s great for tackling hilly terrain or if you just fancy a more "
+ "leisurely ride. With three working modes, you can choose between E-bike, "
+ "assisted bicycle, and normal bike modes.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((13.3260 52.5700, 13.6550 52.5700, 13.6550 52.2700, "
+ "13.3260 52.2700, 13.3260 52.5700))\","
+ " \"store_location\": \"13.4050,52.5200\","
+ " \"brand\": \"Peaknetic\","
+ " \"model\": \"Secto\","
+ " \"price\": 430,"
+ " \"description\": \"If you struggle with stiff fingers or a kinked neck or "
+ "back after a few minutes on the road, this lightweight, aluminum bike alleviates "
+ "those issues and allows you to enjoy the ride. From the ergonomic grips to the "
+ "lumbar-supporting seat position, the Roll Low-Entry offers incredible comfort. "
+ "The rear-inclined seat tube facilitates stability by allowing you to put a foot "
+ "on the ground to balance at a stop, and the low step-over frame makes it "
+ "accessible for all ability and mobility levels. The saddle is very soft, with "
+ "a wide back to support your hip joints and a cutout in the center to redistribute "
+ "that pressure. Rim brakes deliver satisfactory braking control, and the wide tires "
+ "provide a smooth, stable ride on paved roads and gravel. Rack and fender mounts "
+ "facilitate setting up the Roll Low-Entry as your preferred commuter, and the "
+ "BMX-like handlebar offers space for mounting a flashlight, bell, or phone holder.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((1.9450 41.4301, 2.4018 41.4301, 2.4018 41.1987, "
+ "1.9450 41.1987, 1.9450 41.4301))\","
+ " \"store_location\": \"2.1734, 41.3851\","
+ " \"brand\": \"nHill\","
+ " \"model\": \"Summit\","
+ " \"price\": 1200,"
+ " \"description\": \"This budget mountain bike from nHill performs well both "
+ "on bike paths and on the trail. The fork with 100mm of travel absorbs rough "
+ "terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. "
+ "The Shimano Tourney drivetrain offered enough gears for finding a comfortable "
+ "pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. "
+ "Whether you want an affordable bike that you can take to work, but also take "
+ "trail in mountains on the weekends or you’re just after a stable, comfortable "
+ "ride for the bike path, the Summit gives a good value for money.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((12.4464 42.1028, 12.5464 42.1028, "
+ "12.5464 41.7028, 12.4464 41.7028, 12.4464 42.1028))\","
+ " \"store_location\": \"12.4964,41.9028\","
+ " \"model\": \"ThrillCycle\","
+ " \"brand\": \"BikeShind\","
+ " \"price\": 815,"
+ " \"description\": \"An artsy, retro-inspired bicycle that’s as "
+ "functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. "
+ "A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn’t "
+ "suggest taking it to the mountains. Fenders protect you from mud, and a rear "
+ "basket lets you transport groceries, flowers and books. The ThrillCycle comes "
+ "with a limited lifetime warranty, so this little guy will last you long "
+ "past graduation.\","
+ " \"condition\": \"refurbished\""
+ " }"
};
for (int i = 0; i < bicycleJsons.length; i++) {
jedis.jsonSet("bicycle:" + i, Path2.ROOT_PATH, bicycleJsons[i]);
}
SearchResult res1 = jedis.ftSearch("idx:bicycle", "@description: kids");
System.out.println(res1.getTotalResults()); // >>> 2
List<Document> docs1 = res1.getDocuments();
for (int i = 0; i < docs1.size(); i++) {
System.out.println(docs1.get(i).getId());
}
// >>> bicycle:2
// >>> bicycle:1
// Tests for 'ft1' step.
SearchResult res2 = jedis.ftSearch("idx:bicycle", "@model: ka*");
System.out.println(res2.getTotalResults()); // >>> 1
List<Document> docs2 = res2.getDocuments();
for (int i = 0; i < docs2.size(); i++) {
System.out.println(docs2.get(i).getId());
}
// >>> bicycle:4
// Tests for 'ft2' step.
SearchResult res3 = jedis.ftSearch("idx:bicycle", "@brand: *bikes");
System.out.println(res3.getTotalResults()); // >>> 2
List<Document> docs3 = res3.getDocuments();
for (int i = 0; i < docs3.size(); i++) {
System.out.println(docs3.get(i).getId());
}
// >>> bicycle:6
// >>> bicycle:4
// Tests for 'ft3' step.
SearchResult res4 = jedis.ftSearch("idx:bicycle", "%optamized%");
System.out.println(res4.getTotalResults()); // >>> 1
List<Document> docs4 = res4.getDocuments();
for (int i = 0; i < docs4.size(); i++) {
System.out.println(docs4.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft4' step.
SearchResult res5 = jedis.ftSearch("idx:bicycle", "%%optamised%%");
System.out.println(res5.getTotalResults()); // >>> 1
List<Document> docs5 = res5.getDocuments();
for (int i = 0; i < docs5.size(); i++) {
System.out.println(docs5.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft5' step.
jedis.close();
}
}
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NRedisStack.Search.Literals.Enums;
using NRedisStack.Tests;
using StackExchange.Redis;
public class QueryFtExample
{
public void run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
Schema bikeSchema = new Schema()
.AddTextField(new FieldName("$.brand", "brand"))
.AddTextField(new FieldName("$.model", "model"))
.AddTextField(new FieldName("$.description", "description"));
FTCreateParams bikeParams = new FTCreateParams()
.AddPrefix("bicycle:")
.On(IndexDataType.JSON);
db.FT().Create("idx:bicycle", bikeParams, bikeSchema);
var bicycles = new object[]
{
new
{
brand = "Velorim",
model = "Jigger",
price = 270,
description = "Small and powerful, the Jigger is the best ride " +
"for the smallest of tikes! This is the tiniest " +
"kids’ pedal bike on the market available without" +
" a coaster brake, the Jigger is the vehicle of " +
"choice for the rare tenacious little rider " +
"raring to go.",
condition = "used"
},
new
{
brand = "Bicyk",
model = "Hillcraft",
price = 1200,
description = "Kids want to ride with as little weight as possible." +
" Especially on an incline! They may be at the age " +
"when a 27.5 inch wheel bike is just too clumsy coming " +
"off a 24 inch bike. The Hillcraft 26 is just the solution" +
" they need!",
condition = "used",
},
new
{
brand = "Nord",
model = "Chook air 5",
price = 815,
description = "The Chook Air 5 gives kids aged six years and older " +
"a durable and uberlight mountain bike for their first" +
" experience on tracks and easy cruising through forests" +
" and fields. The lower top tube makes it easy to mount" +
" and dismount in any situation, giving your kids greater" +
" safety on the trails.",
condition = "used",
},
new
{
brand = "Eva",
model = "Eva 291",
price = 3400,
description = "The sister company to Nord, Eva launched in 2005 as the" +
" first and only women-dedicated bicycle brand. Designed" +
" by women for women, allEva bikes are optimized for the" +
" feminine physique using analytics from a body metrics" +
" database. If you like 29ers, try the Eva 291. It’s a " +
"brand new bike for 2022.. This full-suspension, " +
"cross-country ride has been designed for velocity. The" +
" 291 has 100mm of front and rear travel, a superlight " +
"aluminum frame and fast-rolling 29-inch wheels. Yippee!",
condition = "used",
},
new
{
brand = "Noka Bikes",
model = "Kahuna",
price = 3200,
description = "Whether you want to try your hand at XC racing or are " +
"looking for a lively trail bike that's just as inspiring" +
" on the climbs as it is over rougher ground, the Wilder" +
" is one heck of a bike built specifically for short women." +
" Both the frames and components have been tweaked to " +
"include a women’s saddle, different bars and unique " +
"colourway.",
condition = "used",
},
new
{
brand = "Breakout",
model = "XBN 2.1 Alloy",
price = 810,
description = "The XBN 2.1 Alloy is our entry-level road bike – but that’s" +
" not to say that it’s a basic machine. With an internal " +
"weld aluminium frame, a full carbon fork, and the slick-shifting" +
" Claris gears from Shimano’s, this is a bike which doesn’t" +
" break the bank and delivers craved performance.",
condition = "new",
},
new
{
brand = "ScramBikes",
model = "WattBike",
price = 2300,
description = "The WattBike is the best e-bike for people who still feel young" +
" at heart. It has a Bafang 1000W mid-drive system and a 48V" +
" 17.5AH Samsung Lithium-Ion battery, allowing you to ride for" +
" more than 60 miles on one charge. It’s great for tackling hilly" +
" terrain or if you just fancy a more leisurely ride. With three" +
" working modes, you can choose between E-bike, assisted bicycle," +
" and normal bike modes.",
condition = "new",
},
new
{
brand = "Peaknetic",
model = "Secto",
price = 430,
description = "If you struggle with stiff fingers or a kinked neck or back after" +
" a few minutes on the road, this lightweight, aluminum bike" +
" alleviates those issues and allows you to enjoy the ride. From" +
" the ergonomic grips to the lumbar-supporting seat position, the" +
" Roll Low-Entry offers incredible comfort. The rear-inclined seat" +
" tube facilitates stability by allowing you to put a foot on the" +
" ground to balance at a stop, and the low step-over frame makes it" +
" accessible for all ability and mobility levels. The saddle is" +
" very soft, with a wide back to support your hip joints and a" +
" cutout in the center to redistribute that pressure. Rim brakes" +
" deliver satisfactory braking control, and the wide tires provide" +
" a smooth, stable ride on paved roads and gravel. Rack and fender" +
" mounts facilitate setting up the Roll Low-Entry as your preferred" +
" commuter, and the BMX-like handlebar offers space for mounting a" +
" flashlight, bell, or phone holder.",
condition = "new",
},
new
{
brand = "nHill",
model = "Summit",
price = 1200,
description = "This budget mountain bike from nHill performs well both on bike" +
" paths and on the trail. The fork with 100mm of travel absorbs" +
" rough terrain. Fat Kenda Booster tires give you grip in corners" +
" and on wet trails. The Shimano Tourney drivetrain offered enough" +
" gears for finding a comfortable pace to ride uphill, and the" +
" Tektro hydraulic disc brakes break smoothly. Whether you want an" +
" affordable bike that you can take to work, but also take trail in" +
" mountains on the weekends or you’re just after a stable," +
" comfortable ride for the bike path, the Summit gives a good value" +
" for money.",
condition = "new",
},
new
{
model = "ThrillCycle",
brand = "BikeShind",
price = 815,
description = "An artsy, retro-inspired bicycle that’s as functional as it is" +
" pretty: The ThrillCycle steel frame offers a smooth ride. A" +
" 9-speed drivetrain has enough gears for coasting in the city, but" +
" we wouldn’t suggest taking it to the mountains. Fenders protect" +
" you from mud, and a rear basket lets you transport groceries," +
" flowers and books. The ThrillCycle comes with a limited lifetime" +
" warranty, so this little guy will last you long past graduation.",
condition = "refurbished",
},
};
for (var i = 0; i < bicycles.Length; i++)
{
db.JSON().Set($"bicycle:{i}", "$", bicycles[i]);
}
SearchResult res1 = db.FT().Search(
"idx:bicycle",
new Query("@description: kids")
);
Console.WriteLine(res1); // >>> 2
// Tests for 'ft1' step.
SearchResult res2 = db.FT().Search(
"idx:bicycle",
new Query("@model: ka*")
);
Console.WriteLine(res2.TotalResults); // >>> 1
// Tests for 'ft2' step.
SearchResult res3 = db.FT().Search(
"idx:bicycle",
new Query("@brand: *bikes")
);
Console.WriteLine(res3.TotalResults); // >>> 2
// Tests for 'ft3' step.
SearchResult res4 = db.FT().Search(
"idx:bicycle",
new Query("%optamized%")
);
Console.WriteLine(res4.TotalResults); // >>> 1
// Tests for 'ft4' step.
SearchResult res5 = db.FT().Search(
"idx:bicycle",
new Query("%%optamised%%")
);
Console.WriteLine(res5.TotalResults); // >>> 1
// Tests for 'ft5' step.
}
}
模糊搜索
模糊搜索允许您找到与搜索词大致匹配的文档。要进行模糊搜索,您需要用%
字符对搜索词进行包裹。单个对表示(Levenshtein)距离为一,两个对表示距离为二,三个对表示最大距离,表示距离为三。
以下是搜索所有文本字段且距离为一的命令:
FT.SEARCH index "%word%"
以下示例查找所有包含一个与错误拼写单词'optamized'距离为一的单词的文档。您可以看到这与单词'optimized'匹配。
FT.SEARCH idx:bicycle "%optamized%"
Are you tired of using redis-cli? Try Redis Insight - the developer GUI for Redis.
import json
import sys
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query
r = redis.Redis(decode_responses=True)
# create index
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)
# load data
with open("data/query_em.json") as f:
bicycles = json.load(f)
pipeline = r.pipeline(transaction=False)
for bid, bicycle in enumerate(bicycles):
pipeline.json().set(f'bicycle:{bid}', Path.root_path(), bicycle)
pipeline.execute()
res = index.search(Query("@description: kids"))
print(res.total)
# >>> 2
res = index.search(Query("@model: ka*"))
print(res.total)
# >>> 1
res = index.search(Query("@brand: *bikes"))
print(res.total)
# >>> 2
res = index.search(Query("%optamized%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
res = index.search(Query("%%optamised%%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
import assert from 'node:assert';
import fs from 'node:fs';
import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps} from 'redis';
const client = createClient();
await client.connect().catch(console.error);
// create index
await client.ft.create('idx:bicycle', {
'$.model': {
type: SchemaFieldTypes.TEXT,
AS: 'model'
},
'$.brand': {
type: SchemaFieldTypes.TEXT,
AS: 'brand'
},
'$.description': {
type: SchemaFieldTypes.TEXT,
AS: 'description'
}
}, {
ON: 'JSON',
PREFIX: 'bicycle:'
})
// load data
const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8'));
await Promise.all(
bicycles.map((bicycle, bid) => {
return client.json.set(`bicycle:${bid}`, '$', bicycle);
})
);
const res1 = await client.ft.search('idx:bicycle', '@description: kids');
console.log(res1.total); // >>> 2
const res2 = await client.ft.search('idx:bicycle', '@model: ka*');
console.log(res2.total); // >>> 1
const res3 = await client.ft.search('idx:bicycle', '@brand: *bikes');
console.log(res3.total); // >>> 2
const res4 = await client.ft.search('idx:bicycle', '%optamized%');
console.log(res4); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
const res5 = await client.ft.search('idx:bicycle', '%%optamised%%');
console.log(res5); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
import java.util.List;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.*;
import redis.clients.jedis.search.schemafields.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.json.Path2;
public class QueryFtExample {
public void run() {
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);
String[] bicycleJsons = new String[] {
" {"
+ " \"pickup_zone\": \"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, "
+ "-74.0610 40.6678, -74.0610 40.7578))\","
+ " \"store_location\": \"-74.0060,40.7128\","
+ " \"brand\": \"Velorim\","
+ " \"model\": \"Jigger\","
+ " \"price\": 270,"
+ " \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! "
+ "This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger "
+ "is the vehicle of choice for the rare tenacious little rider raring to go.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, "
+ "-118.2887 33.9872, -118.2887 34.0972))\","
+ " \"store_location\": \"-118.2437,34.0522\","
+ " \"brand\": \"Bicyk\","
+ " \"model\": \"Hillcraft\","
+ " \"price\": 1200,"
+ " \"description\": \"Kids want to ride with as little weight as possible. Especially "
+ "on an incline! They may be at the age when a 27.5'' wheel bike is just too clumsy coming "
+ "off a 24'' bike. The Hillcraft 26 is just the solution they need!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, "
+ "-87.6848 41.8231, -87.6848 41.9331))\","
+ " \"store_location\": \"-87.6298,41.8781\","
+ " \"brand\": \"Nord\","
+ " \"model\": \"Chook air 5\","
+ " \"price\": 815,"
+ " \"description\": \"The Chook Air 5 gives kids aged six years and older a durable "
+ "and uberlight mountain bike for their first experience on tracks and easy cruising through "
+ "forests and fields. The lower top tube makes it easy to mount and dismount in any "
+ "situation, giving your kids greater safety on the trails.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, "
+ "-80.2433 25.6967, -80.2433 25.8067))\","
+ " \"store_location\": \"-80.1918,25.7617\","
+ " \"brand\": \"Eva\","
+ " \"model\": \"Eva 291\","
+ " \"price\": 3400,"
+ " \"description\": \"The sister company to Nord, Eva launched in 2005 as the first "
+ "and only women-dedicated bicycle brand. Designed by women for women, allEva bikes "
+ "are optimized for the feminine physique using analytics from a body metrics database. "
+ "If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This "
+ "full-suspension, cross-country ride has been designed for velocity. The 291 has "
+ "100mm of front and rear travel, a superlight aluminum frame and fast-rolling "
+ "29-inch wheels. Yippee!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-122.4644 37.8199, -122.3544 37.8199, -122.3544 37.7099, "
+ "-122.4644 37.7099, -122.4644 37.8199))\","
+ " \"store_location\": \"-122.4194,37.7749\","
+ " \"brand\": \"Noka Bikes\","
+ " \"model\": \"Kahuna\","
+ " \"price\": 3200,"
+ " \"description\": \"Whether you want to try your hand at XC racing or are looking "
+ "for a lively trail bike that's just as inspiring on the climbs as it is over rougher "
+ "ground, the Wilder is one heck of a bike built specifically for short women. Both the "
+ "frames and components have been tweaked to include a women’s saddle, different bars "
+ "and unique colourway.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-0.1778 51.5524, 0.0822 51.5524, 0.0822 51.4024, "
+ "-0.1778 51.4024, -0.1778 51.5524))\","
+ " \"store_location\": \"-0.1278,51.5074\","
+ " \"brand\": \"Breakout\","
+ " \"model\": \"XBN 2.1 Alloy\","
+ " \"price\": 810,"
+ " \"description\": \"The XBN 2.1 Alloy is our entry-level road bike – but that’s "
+ "not to say that it’s a basic machine. With an internal weld aluminium frame, a full "
+ "carbon fork, and the slick-shifting Claris gears from Shimano’s, this is a bike which "
+ "doesn’t break the bank and delivers craved performance.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((2.1767 48.9016, 2.5267 48.9016, 2.5267 48.5516, "
+ "2.1767 48.5516, 2.1767 48.9016))\","
+ " \"store_location\": \"2.3522,48.8566\","
+ " \"brand\": \"ScramBikes\","
+ " \"model\": \"WattBike\","
+ " \"price\": 2300,"
+ " \"description\": \"The WattBike is the best e-bike for people who still "
+ "feel young at heart. It has a Bafang 1000W mid-drive system and a 48V 17.5AH "
+ "Samsung Lithium-Ion battery, allowing you to ride for more than 60 miles on one "
+ "charge. It’s great for tackling hilly terrain or if you just fancy a more "
+ "leisurely ride. With three working modes, you can choose between E-bike, "
+ "assisted bicycle, and normal bike modes.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((13.3260 52.5700, 13.6550 52.5700, 13.6550 52.2700, "
+ "13.3260 52.2700, 13.3260 52.5700))\","
+ " \"store_location\": \"13.4050,52.5200\","
+ " \"brand\": \"Peaknetic\","
+ " \"model\": \"Secto\","
+ " \"price\": 430,"
+ " \"description\": \"If you struggle with stiff fingers or a kinked neck or "
+ "back after a few minutes on the road, this lightweight, aluminum bike alleviates "
+ "those issues and allows you to enjoy the ride. From the ergonomic grips to the "
+ "lumbar-supporting seat position, the Roll Low-Entry offers incredible comfort. "
+ "The rear-inclined seat tube facilitates stability by allowing you to put a foot "
+ "on the ground to balance at a stop, and the low step-over frame makes it "
+ "accessible for all ability and mobility levels. The saddle is very soft, with "
+ "a wide back to support your hip joints and a cutout in the center to redistribute "
+ "that pressure. Rim brakes deliver satisfactory braking control, and the wide tires "
+ "provide a smooth, stable ride on paved roads and gravel. Rack and fender mounts "
+ "facilitate setting up the Roll Low-Entry as your preferred commuter, and the "
+ "BMX-like handlebar offers space for mounting a flashlight, bell, or phone holder.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((1.9450 41.4301, 2.4018 41.4301, 2.4018 41.1987, "
+ "1.9450 41.1987, 1.9450 41.4301))\","
+ " \"store_location\": \"2.1734, 41.3851\","
+ " \"brand\": \"nHill\","
+ " \"model\": \"Summit\","
+ " \"price\": 1200,"
+ " \"description\": \"This budget mountain bike from nHill performs well both "
+ "on bike paths and on the trail. The fork with 100mm of travel absorbs rough "
+ "terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. "
+ "The Shimano Tourney drivetrain offered enough gears for finding a comfortable "
+ "pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. "
+ "Whether you want an affordable bike that you can take to work, but also take "
+ "trail in mountains on the weekends or you’re just after a stable, comfortable "
+ "ride for the bike path, the Summit gives a good value for money.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((12.4464 42.1028, 12.5464 42.1028, "
+ "12.5464 41.7028, 12.4464 41.7028, 12.4464 42.1028))\","
+ " \"store_location\": \"12.4964,41.9028\","
+ " \"model\": \"ThrillCycle\","
+ " \"brand\": \"BikeShind\","
+ " \"price\": 815,"
+ " \"description\": \"An artsy, retro-inspired bicycle that’s as "
+ "functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. "
+ "A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn’t "
+ "suggest taking it to the mountains. Fenders protect you from mud, and a rear "
+ "basket lets you transport groceries, flowers and books. The ThrillCycle comes "
+ "with a limited lifetime warranty, so this little guy will last you long "
+ "past graduation.\","
+ " \"condition\": \"refurbished\""
+ " }"
};
for (int i = 0; i < bicycleJsons.length; i++) {
jedis.jsonSet("bicycle:" + i, Path2.ROOT_PATH, bicycleJsons[i]);
}
SearchResult res1 = jedis.ftSearch("idx:bicycle", "@description: kids");
System.out.println(res1.getTotalResults()); // >>> 2
List<Document> docs1 = res1.getDocuments();
for (int i = 0; i < docs1.size(); i++) {
System.out.println(docs1.get(i).getId());
}
// >>> bicycle:2
// >>> bicycle:1
// Tests for 'ft1' step.
SearchResult res2 = jedis.ftSearch("idx:bicycle", "@model: ka*");
System.out.println(res2.getTotalResults()); // >>> 1
List<Document> docs2 = res2.getDocuments();
for (int i = 0; i < docs2.size(); i++) {
System.out.println(docs2.get(i).getId());
}
// >>> bicycle:4
// Tests for 'ft2' step.
SearchResult res3 = jedis.ftSearch("idx:bicycle", "@brand: *bikes");
System.out.println(res3.getTotalResults()); // >>> 2
List<Document> docs3 = res3.getDocuments();
for (int i = 0; i < docs3.size(); i++) {
System.out.println(docs3.get(i).getId());
}
// >>> bicycle:6
// >>> bicycle:4
// Tests for 'ft3' step.
SearchResult res4 = jedis.ftSearch("idx:bicycle", "%optamized%");
System.out.println(res4.getTotalResults()); // >>> 1
List<Document> docs4 = res4.getDocuments();
for (int i = 0; i < docs4.size(); i++) {
System.out.println(docs4.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft4' step.
SearchResult res5 = jedis.ftSearch("idx:bicycle", "%%optamised%%");
System.out.println(res5.getTotalResults()); // >>> 1
List<Document> docs5 = res5.getDocuments();
for (int i = 0; i < docs5.size(); i++) {
System.out.println(docs5.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft5' step.
jedis.close();
}
}
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NRedisStack.Search.Literals.Enums;
using NRedisStack.Tests;
using StackExchange.Redis;
public class QueryFtExample
{
public void run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
Schema bikeSchema = new Schema()
.AddTextField(new FieldName("$.brand", "brand"))
.AddTextField(new FieldName("$.model", "model"))
.AddTextField(new FieldName("$.description", "description"));
FTCreateParams bikeParams = new FTCreateParams()
.AddPrefix("bicycle:")
.On(IndexDataType.JSON);
db.FT().Create("idx:bicycle", bikeParams, bikeSchema);
var bicycles = new object[]
{
new
{
brand = "Velorim",
model = "Jigger",
price = 270,
description = "Small and powerful, the Jigger is the best ride " +
"for the smallest of tikes! This is the tiniest " +
"kids’ pedal bike on the market available without" +
" a coaster brake, the Jigger is the vehicle of " +
"choice for the rare tenacious little rider " +
"raring to go.",
condition = "used"
},
new
{
brand = "Bicyk",
model = "Hillcraft",
price = 1200,
description = "Kids want to ride with as little weight as possible." +
" Especially on an incline! They may be at the age " +
"when a 27.5 inch wheel bike is just too clumsy coming " +
"off a 24 inch bike. The Hillcraft 26 is just the solution" +
" they need!",
condition = "used",
},
new
{
brand = "Nord",
model = "Chook air 5",
price = 815,
description = "The Chook Air 5 gives kids aged six years and older " +
"a durable and uberlight mountain bike for their first" +
" experience on tracks and easy cruising through forests" +
" and fields. The lower top tube makes it easy to mount" +
" and dismount in any situation, giving your kids greater" +
" safety on the trails.",
condition = "used",
},
new
{
brand = "Eva",
model = "Eva 291",
price = 3400,
description = "The sister company to Nord, Eva launched in 2005 as the" +
" first and only women-dedicated bicycle brand. Designed" +
" by women for women, allEva bikes are optimized for the" +
" feminine physique using analytics from a body metrics" +
" database. If you like 29ers, try the Eva 291. It’s a " +
"brand new bike for 2022.. This full-suspension, " +
"cross-country ride has been designed for velocity. The" +
" 291 has 100mm of front and rear travel, a superlight " +
"aluminum frame and fast-rolling 29-inch wheels. Yippee!",
condition = "used",
},
new
{
brand = "Noka Bikes",
model = "Kahuna",
price = 3200,
description = "Whether you want to try your hand at XC racing or are " +
"looking for a lively trail bike that's just as inspiring" +
" on the climbs as it is over rougher ground, the Wilder" +
" is one heck of a bike built specifically for short women." +
" Both the frames and components have been tweaked to " +
"include a women’s saddle, different bars and unique " +
"colourway.",
condition = "used",
},
new
{
brand = "Breakout",
model = "XBN 2.1 Alloy",
price = 810,
description = "The XBN 2.1 Alloy is our entry-level road bike – but that’s" +
" not to say that it’s a basic machine. With an internal " +
"weld aluminium frame, a full carbon fork, and the slick-shifting" +
" Claris gears from Shimano’s, this is a bike which doesn’t" +
" break the bank and delivers craved performance.",
condition = "new",
},
new
{
brand = "ScramBikes",
model = "WattBike",
price = 2300,
description = "The WattBike is the best e-bike for people who still feel young" +
" at heart. It has a Bafang 1000W mid-drive system and a 48V" +
" 17.5AH Samsung Lithium-Ion battery, allowing you to ride for" +
" more than 60 miles on one charge. It’s great for tackling hilly" +
" terrain or if you just fancy a more leisurely ride. With three" +
" working modes, you can choose between E-bike, assisted bicycle," +
" and normal bike modes.",
condition = "new",
},
new
{
brand = "Peaknetic",
model = "Secto",
price = 430,
description = "If you struggle with stiff fingers or a kinked neck or back after" +
" a few minutes on the road, this lightweight, aluminum bike" +
" alleviates those issues and allows you to enjoy the ride. From" +
" the ergonomic grips to the lumbar-supporting seat position, the" +
" Roll Low-Entry offers incredible comfort. The rear-inclined seat" +
" tube facilitates stability by allowing you to put a foot on the" +
" ground to balance at a stop, and the low step-over frame makes it" +
" accessible for all ability and mobility levels. The saddle is" +
" very soft, with a wide back to support your hip joints and a" +
" cutout in the center to redistribute that pressure. Rim brakes" +
" deliver satisfactory braking control, and the wide tires provide" +
" a smooth, stable ride on paved roads and gravel. Rack and fender" +
" mounts facilitate setting up the Roll Low-Entry as your preferred" +
" commuter, and the BMX-like handlebar offers space for mounting a" +
" flashlight, bell, or phone holder.",
condition = "new",
},
new
{
brand = "nHill",
model = "Summit",
price = 1200,
description = "This budget mountain bike from nHill performs well both on bike" +
" paths and on the trail. The fork with 100mm of travel absorbs" +
" rough terrain. Fat Kenda Booster tires give you grip in corners" +
" and on wet trails. The Shimano Tourney drivetrain offered enough" +
" gears for finding a comfortable pace to ride uphill, and the" +
" Tektro hydraulic disc brakes break smoothly. Whether you want an" +
" affordable bike that you can take to work, but also take trail in" +
" mountains on the weekends or you’re just after a stable," +
" comfortable ride for the bike path, the Summit gives a good value" +
" for money.",
condition = "new",
},
new
{
model = "ThrillCycle",
brand = "BikeShind",
price = 815,
description = "An artsy, retro-inspired bicycle that’s as functional as it is" +
" pretty: The ThrillCycle steel frame offers a smooth ride. A" +
" 9-speed drivetrain has enough gears for coasting in the city, but" +
" we wouldn’t suggest taking it to the mountains. Fenders protect" +
" you from mud, and a rear basket lets you transport groceries," +
" flowers and books. The ThrillCycle comes with a limited lifetime" +
" warranty, so this little guy will last you long past graduation.",
condition = "refurbished",
},
};
for (var i = 0; i < bicycles.Length; i++)
{
db.JSON().Set($"bicycle:{i}", "$", bicycles[i]);
}
SearchResult res1 = db.FT().Search(
"idx:bicycle",
new Query("@description: kids")
);
Console.WriteLine(res1); // >>> 2
// Tests for 'ft1' step.
SearchResult res2 = db.FT().Search(
"idx:bicycle",
new Query("@model: ka*")
);
Console.WriteLine(res2.TotalResults); // >>> 1
// Tests for 'ft2' step.
SearchResult res3 = db.FT().Search(
"idx:bicycle",
new Query("@brand: *bikes")
);
Console.WriteLine(res3.TotalResults); // >>> 2
// Tests for 'ft3' step.
SearchResult res4 = db.FT().Search(
"idx:bicycle",
new Query("%optamized%")
);
Console.WriteLine(res4.TotalResults); // >>> 1
// Tests for 'ft4' step.
SearchResult res5 = db.FT().Search(
"idx:bicycle",
new Query("%%optamised%%")
);
Console.WriteLine(res5.TotalResults); // >>> 1
// Tests for 'ft5' step.
}
}
如果你想将最大词距增加到两个,可以使用以下查询:
FT.SEARCH idx:bicycle "%%optamised%%"
Are you tired of using redis-cli? Try Redis Insight - the developer GUI for Redis.
import json
import sys
import redis
from redis.commands.json.path import Path
from redis.commands.search.field import TextField, NumericField, TagField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis.commands.search.query import NumericFilter, Query
r = redis.Redis(decode_responses=True)
# create index
schema = (
TextField("$.brand", as_name="brand"),
TextField("$.model", as_name="model"),
TextField("$.description", as_name="description"),
)
index = r.ft("idx:bicycle")
index.create_index(
schema,
definition=IndexDefinition(prefix=["bicycle:"], index_type=IndexType.JSON),
)
# load data
with open("data/query_em.json") as f:
bicycles = json.load(f)
pipeline = r.pipeline(transaction=False)
for bid, bicycle in enumerate(bicycles):
pipeline.json().set(f'bicycle:{bid}', Path.root_path(), bicycle)
pipeline.execute()
res = index.search(Query("@description: kids"))
print(res.total)
# >>> 2
res = index.search(Query("@model: ka*"))
print(res.total)
# >>> 1
res = index.search(Query("@brand: *bikes"))
print(res.total)
# >>> 2
res = index.search(Query("%optamized%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
res = index.search(Query("%%optamised%%"))
print(res)
# >>> Result{1 total, docs: [Document {'id': 'bicycle:3', 'payload': None, 'json': '{"pickup_zone":"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, -80.2433 25.6967, -80.2433 25.8067))","store_location":"-80.1918,25.7617","brand":"Eva","model":"Eva 291","price":3400,"description":"The sister company to Nord, Eva launched in 2005 as the first and only women-dedicated bicycle brand. Designed by women for women, allEva bikes are optimized for the feminine physique using analytics from a body metrics database. If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This full-suspension, cross-country ride has been designed for velocity. The 291 has 100mm of front and rear travel, a superlight aluminum frame and fast-rolling 29-inch wheels. Yippee!","condition":"used"}'}]}
import assert from 'node:assert';
import fs from 'node:fs';
import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps} from 'redis';
const client = createClient();
await client.connect().catch(console.error);
// create index
await client.ft.create('idx:bicycle', {
'$.model': {
type: SchemaFieldTypes.TEXT,
AS: 'model'
},
'$.brand': {
type: SchemaFieldTypes.TEXT,
AS: 'brand'
},
'$.description': {
type: SchemaFieldTypes.TEXT,
AS: 'description'
}
}, {
ON: 'JSON',
PREFIX: 'bicycle:'
})
// load data
const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8'));
await Promise.all(
bicycles.map((bicycle, bid) => {
return client.json.set(`bicycle:${bid}`, '$', bicycle);
})
);
const res1 = await client.ft.search('idx:bicycle', '@description: kids');
console.log(res1.total); // >>> 2
const res2 = await client.ft.search('idx:bicycle', '@model: ka*');
console.log(res2.total); // >>> 1
const res3 = await client.ft.search('idx:bicycle', '@brand: *bikes');
console.log(res3.total); // >>> 2
const res4 = await client.ft.search('idx:bicycle', '%optamized%');
console.log(res4); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
const res5 = await client.ft.search('idx:bicycle', '%%optamised%%');
console.log(res5); // >>> { total: 1, documents: [ { id: 'bicycle:3', value: [Object: null prototype] } ]}
import java.util.List;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.*;
import redis.clients.jedis.search.schemafields.*;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.json.Path2;
public class QueryFtExample {
public void run() {
UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379");
SchemaField[] schema = {
TextField.of("$.brand").as("brand"),
TextField.of("$.model").as("model"),
TextField.of("$.description").as("description"),
NumericField.of("$.price").as("price"),
TagField.of("$.condition").as("condition")
};
jedis.ftCreate("idx:bicycle",
FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("bicycle:"),
schema
);
String[] bicycleJsons = new String[] {
" {"
+ " \"pickup_zone\": \"POLYGON((-74.0610 40.7578, -73.9510 40.7578, -73.9510 40.6678, "
+ "-74.0610 40.6678, -74.0610 40.7578))\","
+ " \"store_location\": \"-74.0060,40.7128\","
+ " \"brand\": \"Velorim\","
+ " \"model\": \"Jigger\","
+ " \"price\": 270,"
+ " \"description\": \"Small and powerful, the Jigger is the best ride for the smallest of tikes! "
+ "This is the tiniest kids’ pedal bike on the market available without a coaster brake, the Jigger "
+ "is the vehicle of choice for the rare tenacious little rider raring to go.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-118.2887 34.0972, -118.1987 34.0972, -118.1987 33.9872, "
+ "-118.2887 33.9872, -118.2887 34.0972))\","
+ " \"store_location\": \"-118.2437,34.0522\","
+ " \"brand\": \"Bicyk\","
+ " \"model\": \"Hillcraft\","
+ " \"price\": 1200,"
+ " \"description\": \"Kids want to ride with as little weight as possible. Especially "
+ "on an incline! They may be at the age when a 27.5'' wheel bike is just too clumsy coming "
+ "off a 24'' bike. The Hillcraft 26 is just the solution they need!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-87.6848 41.9331, -87.5748 41.9331, -87.5748 41.8231, "
+ "-87.6848 41.8231, -87.6848 41.9331))\","
+ " \"store_location\": \"-87.6298,41.8781\","
+ " \"brand\": \"Nord\","
+ " \"model\": \"Chook air 5\","
+ " \"price\": 815,"
+ " \"description\": \"The Chook Air 5 gives kids aged six years and older a durable "
+ "and uberlight mountain bike for their first experience on tracks and easy cruising through "
+ "forests and fields. The lower top tube makes it easy to mount and dismount in any "
+ "situation, giving your kids greater safety on the trails.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-80.2433 25.8067, -80.1333 25.8067, -80.1333 25.6967, "
+ "-80.2433 25.6967, -80.2433 25.8067))\","
+ " \"store_location\": \"-80.1918,25.7617\","
+ " \"brand\": \"Eva\","
+ " \"model\": \"Eva 291\","
+ " \"price\": 3400,"
+ " \"description\": \"The sister company to Nord, Eva launched in 2005 as the first "
+ "and only women-dedicated bicycle brand. Designed by women for women, allEva bikes "
+ "are optimized for the feminine physique using analytics from a body metrics database. "
+ "If you like 29ers, try the Eva 291. It’s a brand new bike for 2022.. This "
+ "full-suspension, cross-country ride has been designed for velocity. The 291 has "
+ "100mm of front and rear travel, a superlight aluminum frame and fast-rolling "
+ "29-inch wheels. Yippee!\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-122.4644 37.8199, -122.3544 37.8199, -122.3544 37.7099, "
+ "-122.4644 37.7099, -122.4644 37.8199))\","
+ " \"store_location\": \"-122.4194,37.7749\","
+ " \"brand\": \"Noka Bikes\","
+ " \"model\": \"Kahuna\","
+ " \"price\": 3200,"
+ " \"description\": \"Whether you want to try your hand at XC racing or are looking "
+ "for a lively trail bike that's just as inspiring on the climbs as it is over rougher "
+ "ground, the Wilder is one heck of a bike built specifically for short women. Both the "
+ "frames and components have been tweaked to include a women’s saddle, different bars "
+ "and unique colourway.\","
+ " \"condition\": \"used\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((-0.1778 51.5524, 0.0822 51.5524, 0.0822 51.4024, "
+ "-0.1778 51.4024, -0.1778 51.5524))\","
+ " \"store_location\": \"-0.1278,51.5074\","
+ " \"brand\": \"Breakout\","
+ " \"model\": \"XBN 2.1 Alloy\","
+ " \"price\": 810,"
+ " \"description\": \"The XBN 2.1 Alloy is our entry-level road bike – but that’s "
+ "not to say that it’s a basic machine. With an internal weld aluminium frame, a full "
+ "carbon fork, and the slick-shifting Claris gears from Shimano’s, this is a bike which "
+ "doesn’t break the bank and delivers craved performance.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((2.1767 48.9016, 2.5267 48.9016, 2.5267 48.5516, "
+ "2.1767 48.5516, 2.1767 48.9016))\","
+ " \"store_location\": \"2.3522,48.8566\","
+ " \"brand\": \"ScramBikes\","
+ " \"model\": \"WattBike\","
+ " \"price\": 2300,"
+ " \"description\": \"The WattBike is the best e-bike for people who still "
+ "feel young at heart. It has a Bafang 1000W mid-drive system and a 48V 17.5AH "
+ "Samsung Lithium-Ion battery, allowing you to ride for more than 60 miles on one "
+ "charge. It’s great for tackling hilly terrain or if you just fancy a more "
+ "leisurely ride. With three working modes, you can choose between E-bike, "
+ "assisted bicycle, and normal bike modes.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((13.3260 52.5700, 13.6550 52.5700, 13.6550 52.2700, "
+ "13.3260 52.2700, 13.3260 52.5700))\","
+ " \"store_location\": \"13.4050,52.5200\","
+ " \"brand\": \"Peaknetic\","
+ " \"model\": \"Secto\","
+ " \"price\": 430,"
+ " \"description\": \"If you struggle with stiff fingers or a kinked neck or "
+ "back after a few minutes on the road, this lightweight, aluminum bike alleviates "
+ "those issues and allows you to enjoy the ride. From the ergonomic grips to the "
+ "lumbar-supporting seat position, the Roll Low-Entry offers incredible comfort. "
+ "The rear-inclined seat tube facilitates stability by allowing you to put a foot "
+ "on the ground to balance at a stop, and the low step-over frame makes it "
+ "accessible for all ability and mobility levels. The saddle is very soft, with "
+ "a wide back to support your hip joints and a cutout in the center to redistribute "
+ "that pressure. Rim brakes deliver satisfactory braking control, and the wide tires "
+ "provide a smooth, stable ride on paved roads and gravel. Rack and fender mounts "
+ "facilitate setting up the Roll Low-Entry as your preferred commuter, and the "
+ "BMX-like handlebar offers space for mounting a flashlight, bell, or phone holder.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((1.9450 41.4301, 2.4018 41.4301, 2.4018 41.1987, "
+ "1.9450 41.1987, 1.9450 41.4301))\","
+ " \"store_location\": \"2.1734, 41.3851\","
+ " \"brand\": \"nHill\","
+ " \"model\": \"Summit\","
+ " \"price\": 1200,"
+ " \"description\": \"This budget mountain bike from nHill performs well both "
+ "on bike paths and on the trail. The fork with 100mm of travel absorbs rough "
+ "terrain. Fat Kenda Booster tires give you grip in corners and on wet trails. "
+ "The Shimano Tourney drivetrain offered enough gears for finding a comfortable "
+ "pace to ride uphill, and the Tektro hydraulic disc brakes break smoothly. "
+ "Whether you want an affordable bike that you can take to work, but also take "
+ "trail in mountains on the weekends or you’re just after a stable, comfortable "
+ "ride for the bike path, the Summit gives a good value for money.\","
+ " \"condition\": \"new\""
+ " }",
" {"
+ " \"pickup_zone\": \"POLYGON((12.4464 42.1028, 12.5464 42.1028, "
+ "12.5464 41.7028, 12.4464 41.7028, 12.4464 42.1028))\","
+ " \"store_location\": \"12.4964,41.9028\","
+ " \"model\": \"ThrillCycle\","
+ " \"brand\": \"BikeShind\","
+ " \"price\": 815,"
+ " \"description\": \"An artsy, retro-inspired bicycle that’s as "
+ "functional as it is pretty: The ThrillCycle steel frame offers a smooth ride. "
+ "A 9-speed drivetrain has enough gears for coasting in the city, but we wouldn’t "
+ "suggest taking it to the mountains. Fenders protect you from mud, and a rear "
+ "basket lets you transport groceries, flowers and books. The ThrillCycle comes "
+ "with a limited lifetime warranty, so this little guy will last you long "
+ "past graduation.\","
+ " \"condition\": \"refurbished\""
+ " }"
};
for (int i = 0; i < bicycleJsons.length; i++) {
jedis.jsonSet("bicycle:" + i, Path2.ROOT_PATH, bicycleJsons[i]);
}
SearchResult res1 = jedis.ftSearch("idx:bicycle", "@description: kids");
System.out.println(res1.getTotalResults()); // >>> 2
List<Document> docs1 = res1.getDocuments();
for (int i = 0; i < docs1.size(); i++) {
System.out.println(docs1.get(i).getId());
}
// >>> bicycle:2
// >>> bicycle:1
// Tests for 'ft1' step.
SearchResult res2 = jedis.ftSearch("idx:bicycle", "@model: ka*");
System.out.println(res2.getTotalResults()); // >>> 1
List<Document> docs2 = res2.getDocuments();
for (int i = 0; i < docs2.size(); i++) {
System.out.println(docs2.get(i).getId());
}
// >>> bicycle:4
// Tests for 'ft2' step.
SearchResult res3 = jedis.ftSearch("idx:bicycle", "@brand: *bikes");
System.out.println(res3.getTotalResults()); // >>> 2
List<Document> docs3 = res3.getDocuments();
for (int i = 0; i < docs3.size(); i++) {
System.out.println(docs3.get(i).getId());
}
// >>> bicycle:6
// >>> bicycle:4
// Tests for 'ft3' step.
SearchResult res4 = jedis.ftSearch("idx:bicycle", "%optamized%");
System.out.println(res4.getTotalResults()); // >>> 1
List<Document> docs4 = res4.getDocuments();
for (int i = 0; i < docs4.size(); i++) {
System.out.println(docs4.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft4' step.
SearchResult res5 = jedis.ftSearch("idx:bicycle", "%%optamised%%");
System.out.println(res5.getTotalResults()); // >>> 1
List<Document> docs5 = res5.getDocuments();
for (int i = 0; i < docs5.size(); i++) {
System.out.println(docs5.get(i).getId());
}
// >>> bicycle:3
// Tests for 'ft5' step.
jedis.close();
}
}
using NRedisStack.RedisStackCommands;
using NRedisStack.Search;
using NRedisStack.Search.Literals.Enums;
using NRedisStack.Tests;
using StackExchange.Redis;
public class QueryFtExample
{
public void run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
Schema bikeSchema = new Schema()
.AddTextField(new FieldName("$.brand", "brand"))
.AddTextField(new FieldName("$.model", "model"))
.AddTextField(new FieldName("$.description", "description"));
FTCreateParams bikeParams = new FTCreateParams()
.AddPrefix("bicycle:")
.On(IndexDataType.JSON);
db.FT().Create("idx:bicycle", bikeParams, bikeSchema);
var bicycles = new object[]
{
new
{
brand = "Velorim",
model = "Jigger",
price = 270,
description = "Small and powerful, the Jigger is the best ride " +
"for the smallest of tikes! This is the tiniest " +
"kids’ pedal bike on the market available without" +
" a coaster brake, the Jigger is the vehicle of " +
"choice for the rare tenacious little rider " +
"raring to go.",
condition = "used"
},
new
{
brand = "Bicyk",
model = "Hillcraft",
price = 1200,
description = "Kids want to ride with as little weight as possible." +
" Especially on an incline! They may be at the age " +
"when a 27.5 inch wheel bike is just too clumsy coming " +
"off a 24 inch bike. The Hillcraft 26 is just the solution" +
" they need!",
condition = "used",
},
new
{
brand = "Nord",
model = "Chook air 5",
price = 815,
description = "The Chook Air 5 gives kids aged six years and older " +
"a durable and uberlight mountain bike for their first" +
" experience on tracks and easy cruising through forests" +
" and fields. The lower top tube makes it easy to mount" +
" and dismount in any situation, giving your kids greater" +
" safety on the trails.",
condition = "used",
},
new
{
brand = "Eva",
model = "Eva 291",
price = 3400,
description = "The sister company to Nord, Eva launched in 2005 as the" +
" first and only women-dedicated bicycle brand. Designed" +
" by women for women, allEva bikes are optimized for the" +
" feminine physique using analytics from a body metrics" +
" database. If you like 29ers, try the Eva 291. It’s a " +
"brand new bike for 2022.. This full-suspension, " +
"cross-country ride has been designed for velocity. The" +
" 291 has 100mm of front and rear travel, a superlight " +
"aluminum frame and fast-rolling 29-inch wheels. Yippee!",
condition = "used",
},
new
{
brand = "Noka Bikes",
model = "Kahuna",
price = 3200,
description = "Whether you want to try your hand at XC racing or are " +
"looking for a lively trail bike that's just as inspiring" +
" on the climbs as it is over rougher ground, the Wilder" +
" is one heck of a bike built specifically for short women." +
" Both the frames and components have been tweaked to " +
"include a women’s saddle, different bars and unique " +
"colourway.",
condition = "used",
},
new
{
brand = "Breakout",
model = "XBN 2.1 Alloy",
price = 810,
description = "The XBN 2.1 Alloy is our entry-level road bike – but that’s" +
" not to say that it’s a basic machine. With an internal " +
"weld aluminium frame, a full carbon fork, and the slick-shifting" +
" Claris gears from Shimano’s, this is a bike which doesn’t" +
" break the bank and delivers craved performance.",
condition = "new",
},
new
{
brand = "ScramBikes",
model = "WattBike",
price = 2300,
description = "The WattBike is the best e-bike for people who still feel young" +
" at heart. It has a Bafang 1000W mid-drive system and a 48V" +
" 17.5AH Samsung Lithium-Ion battery, allowing you to ride for" +
" more than 60 miles on one charge. It’s great for tackling hilly" +
" terrain or if you just fancy a more leisurely ride. With three" +
" working modes, you can choose between E-bike, assisted bicycle," +
" and normal bike modes.",
condition = "new",
},
new
{
brand = "Peaknetic",
model = "Secto",
price = 430,
description = "If you struggle with stiff fingers or a kinked neck or back after" +
" a few minutes on the road, this lightweight, aluminum bike" +
" alleviates those issues and allows you to enjoy the ride. From" +
" the ergonomic grips to the lumbar-supporting seat position, the" +
" Roll Low-Entry offers incredible comfort. The rear-inclined seat" +
" tube facilitates stability by allowing you to put a foot on the" +
" ground to balance at a stop, and the low step-over frame makes it" +
" accessible for all ability and mobility levels. The saddle is" +
" very soft, with a wide back to support your hip joints and a" +
" cutout in the center to redistribute that pressure. Rim brakes" +
" deliver satisfactory braking control, and the wide tires provide" +
" a smooth, stable ride on paved roads and gravel. Rack and fender" +
" mounts facilitate setting up the Roll Low-Entry as your preferred" +
" commuter, and the BMX-like handlebar offers space for mounting a" +
" flashlight, bell, or phone holder.",
condition = "new",
},
new
{
brand = "nHill",
model = "Summit",
price = 1200,
description = "This budget mountain bike from nHill performs well both on bike" +
" paths and on the trail. The fork with 100mm of travel absorbs" +
" rough terrain. Fat Kenda Booster tires give you grip in corners" +
" and on wet trails. The Shimano Tourney drivetrain offered enough" +
" gears for finding a comfortable pace to ride uphill, and the" +
" Tektro hydraulic disc brakes break smoothly. Whether you want an" +
" affordable bike that you can take to work, but also take trail in" +
" mountains on the weekends or you’re just after a stable," +
" comfortable ride for the bike path, the Summit gives a good value" +
" for money.",
condition = "new",
},
new
{
model = "ThrillCycle",
brand = "BikeShind",
price = 815,
description = "An artsy, retro-inspired bicycle that’s as functional as it is" +
" pretty: The ThrillCycle steel frame offers a smooth ride. A" +
" 9-speed drivetrain has enough gears for coasting in the city, but" +
" we wouldn’t suggest taking it to the mountains. Fenders protect" +
" you from mud, and a rear basket lets you transport groceries," +
" flowers and books. The ThrillCycle comes with a limited lifetime" +
" warranty, so this little guy will last you long past graduation.",
condition = "refurbished",
},
};
for (var i = 0; i < bicycles.Length; i++)
{
db.JSON().Set($"bicycle:{i}", "$", bicycles[i]);
}
SearchResult res1 = db.FT().Search(
"idx:bicycle",
new Query("@description: kids")
);
Console.WriteLine(res1); // >>> 2
// Tests for 'ft1' step.
SearchResult res2 = db.FT().Search(
"idx:bicycle",
new Query("@model: ka*")
);
Console.WriteLine(res2.TotalResults); // >>> 1
// Tests for 'ft2' step.
SearchResult res3 = db.FT().Search(
"idx:bicycle",
new Query("@brand: *bikes")
);
Console.WriteLine(res3.TotalResults); // >>> 2
// Tests for 'ft3' step.
SearchResult res4 = db.FT().Search(
"idx:bicycle",
new Query("%optamized%")
);
Console.WriteLine(res4.TotalResults); // >>> 1
// Tests for 'ft4' step.
SearchResult res5 = db.FT().Search(
"idx:bicycle",
new Query("%%optamised%%")
);
Console.WriteLine(res5.TotalResults); // >>> 1
// Tests for 'ft5' step.
}
}