赞
踩
推荐使用docker安装,使用以下命令即可安装并启动redisearch
docker run -p 6379:6379 redislabs/redisearch:latest
通过下载redisearch二进制文件,将二进制文件加载进redis模块的方式好像对于开源的redis版本不能使用 ,要商业版的才可以。(因为我使用开源redis用了一天,就提示我不能使用了)
使用RediSearch来搜索数据之前,我们得先创建下索引:
- FT.CREATE {index}
- [ON {data_type}]
- [PREFIX {count} {prefix} [{prefix} ..]
- [LANGUAGE {default_lang}]
- SCHEMA {identifier} [AS {attribute}]
- [TEXT | NUMERIC | GEO | TAG ] [CASESENSITIVE]
- [SORTABLE] [NOINDEX]] ...
FT.CREATE
命令可以建立索引,语法中的参数意义如下;
看一下官方文档是怎么使用的https://redis.io/docs/stack/search/quick_start/
使用FT.CREATE命令创建具有字段和权重的索引(默认权重为 1.0):
- 127.0.0.1:6379> FT.CREATE myIdx ON HASH PREFIX 1 doc: SCHEMA title TEXT WEIGHT 5.0 body TEXT url TEXT
- OK
此时,任何带有前缀的键的现有哈希文档都会doc:
自动添加到索引中。
创建索引后,任何带有doc:
前缀的新哈希文档都会在创建时自动建立索引。
- 127.0.0.1:6379> HSET doc:1 title "hello world" body "lorem ipsum" url "http://redis.io"
- (integer) 3
要在索引中搜索包含特定单词的文档,请使用以下FT.SEARCH命令:
- 127.0.0.1:6379> FT.SEARCH myIdx "hello world" LIMIT 0 10
- 1) (integer) 1
- 2) "doc:1"
- 3) 1) "title"
- 2) "hello world"
- 3) "body"
- 4) "lorem ipsum"
- 5) "url"
- 6) "http://redis.io"
要删除索引而不删除关联的哈希文档
- 127.0.0.1:6379> FT.DROPINDEX myIdx
- OK
更多命令使用还可以看看这篇文章https://zhuanlan.zhihu.com/p/478548947
导入maven坐标
- <dependency>
- <groupId>com.redislabs</groupId>
- <artifactId>jredisearch</artifactId>
- <version>1.8.1</version>
- </dependency>
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.3.10</version>
- </dependency>
- <dependency>
- <groupId>com.hankcs</groupId>
- <artifactId>hanlp</artifactId>
- <version>portable-1.7.8</version>
- </dependency>
配置类,注入Client对象
- @Configuration
- public class RSclientConfig {
- @Bean
- public Client setClient(){
- /*
- Client 是主要的 RediSearch 客户端类,包装了连接管理和所有 RediSearch 命令
- 连接redisearch
- "store"索引(相当于表)
- */
- Client client = new Client("store", host, port);
- return client;
- }
- }
rediSearch工具类
- import io.redisearch.*;
- import io.redisearch.aggregation.AggregationBuilder;
- import io.redisearch.aggregation.SortedField;
- import io.redisearch.aggregation.reducers.Reducers;
- import io.redisearch.client.AddOptions;
- import io.redisearch.client.Client;
- import io.redisearch.querybuilder.GeoValue;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import java.util.HashMap;
- import java.util.Map;
-
- @Slf4j
- @Component
- public class RedisSearchUtilsV2 {
- @Autowired
- private Client client;
-
- /**
- * 删除索引
- */
- public void dropIndex(){
- // 只会删除索引,不会删除索引相关的文档,true:表示如果索引不存在,直接返回false,不报错
- client.dropIndex(true);
- }
-
- /**
- * 删除文档数据
- */
- public void deleteDocuments(String ...docs){
- // 传入一组(将删除的文档ID)
- client.deleteDocuments(true,docs);
- }
-
- /**修改文档**/
- public void updateDocument(String docId, double score, Map map){
- client.updateDocument(docId,score,map);
- }
-
- /**添加数据8**/
- public boolean addHashData(){
- try{
- // FullText类型(全文查询)
- Schema.Field storeName = new Schema.Field("storeName", Schema.FieldType.FullText,false);
- Schema.Field storeIntroduce = new Schema.Field("storeIntroduce", Schema.FieldType.FullText,false);
- // tag类型
- Schema.Field tag = new Schema.Field("tag", Schema.FieldType.Tag,false);
- // geo类型,经纬度
- Schema.Field location = new Schema.Field("location", Schema.FieldType.Geo,false);
- // number类型(此类型可以范围查询),true:允许排序
- Schema.Field start = new Schema.Field("start", Schema.FieldType.Numeric,true);
-
- // 定义一个索引模式(相当于student的表结构)
- Schema schema = new Schema()
- .addField(storeName)
- .addField(storeIntroduce)
- .addField(tag)
- //.addField(location)// 加上Geo类型后,无法查询出数据,暂时不知道什么原因
- .addField(start);
-
-
- // 创建索引(如果存在相同的索引则会创建失败)
- client.createIndex(schema, Client.IndexOptions.Default());
-
- // 创建一些map数据,准备存入student索引
- Map<String, Object> fields1 = createDocument("粥铺", "我家小米粥好喝", "满减"
- ,new GeoValue(106.555697,29.613248,5000, GeoValue.Unit.METERS),300);
-
- Map<String, Object> fields2 = createDocument("米铺", "我家米便宜好吃", "香米"
- ,new GeoValue(106.555661,29.613695,100, GeoValue.Unit.METERS),100);
-
- Map<String, Object> fields3 = createDocument("米通信", "电子批发城", "电子"
- ,new GeoValue(106.555922,29.613429,100, GeoValue.Unit.METERS),120);
-
- Map<String, Object> fields4 = createDocument("熊猫家居", "只为让你有更好的舒适生活", "家居"
- ,new GeoValue(106.555922,29.613429,100, GeoValue.Unit.METERS),220);
-
- Map<String, Object> fields5 = createDocument("河马家居", "为你私人定制", "家居"
- ,new GeoValue(106.555571,29.612973,100, GeoValue.Unit.METERS),60);
-
-
- // 创建选项,设置语言为中文,否则无法进行中文分词查询
- AddOptions options = new AddOptions();
- options.setLanguage("chinese");
-
- /*
- 创建文档(相当于表的每一行数据)id:"doc1" fields:fields1 score:1
- id:唯一值,否则创建失败,且必须为string;
- fields:需要存放的数据(默认为Map类型);
- score:分数(权重0~1)
- */
- Document doc1 = new Document("doc1", fields1,1);
- Document doc2 = new Document("doc2", fields2,0.7);
- Document doc3 = new Document("doc3", fields3,0.5);
- Document doc4 = new Document("doc4", fields4,0.3);
- Document doc5 = new Document("doc5", fields5,0.1);
-
- // 添加文档,将设置项加进去
- client.addDocument(doc1,options);
- client.addDocument(doc2,options);
- client.addDocument(doc3,options);
- client.addDocument(doc4,options);
- client.addDocument(doc5,options);
- }catch (Exception e){
- e.printStackTrace();
- log.info("文档添加失败!");
- return false;
- }
- log.info("文档添加成功!");
- return true;
- }
-
- /**根据关键字全文查询
- * @method limit(0,3) 从位置0开始查询出3条
- * @method setWithScores() 按分数大小查询(权重),从大到小排
- * @method setLanguage("chinese") 默认不支持中文分词,所以要设置语言
- * @method highlightFields("title","body") 设置哪些字段需要高亮显示
- */
- public SearchResult searchByKey(String queryString) {
-
- // 创建查询语句
- Query query = new Query(queryString)
- .limit(0,3)
- .setWithScores()
- .highlightFields("storeName","storeIntroduce")
- .setLanguage("chinese");
-
- // 提交查询
- SearchResult result = client.search(query);
- // 输出
- show(result);
- return result;
- }
-
- /**根据数值范围+key查询
- *
- * @method addFilter()
- * 添加过滤器
- * @method Query.NumericFilter(field,min,max)
- * 数值过滤器
- * 查询字段field范围(min,max)
- * **/
- public SearchResult searchByNumberRange(String key, String field, int min, int max){
-
- Query query = new Query(key)
- .addFilter(new Query.NumericFilter(field,min,max))
- .limit(0,3)
- .setLanguage("chinese");
- // 提交查询
- SearchResult result = client.search(query);
- // 输出
- show(result);
- return result;
- }
-
- /**位置范围+key查询
- * new Query.GeoFilter("location",lon,lat,radius,unit)
- * 经纬度过滤器
- * @param key 搜索关键词
- * @param lon 经度
- * @param lat 纬度
- * @param radius 半径
- * @param unit 度量单位
- * **/
- public SearchResult searchByGeoRange(String key, double lon, double lat, double radius, String unit){
- Query query = new Query(key)
- .addFilter(new Query.GeoFilter("location",lon,lat,radius,unit))
- .limit(0,3)
- .setLanguage("chinese");
- // 提交查询
- SearchResult result = client.search(query);
-
- show(result);
- return result;
- }
-
- /**
- * 聚合查询
- * @param query
- * @param start
- * @param state
- * @param avgprice
- * @param k
- * @return
- */
- public AggregationResult aggregate(String query, String start, String state, String avgprice, String k){
- AggregationBuilder builder =new AggregationBuilder(query)
- .apply("@".concat(start).concat("/1000"), k)
- .groupBy("@".concat(state), Reducers.avg("@".concat(k)).as(avgprice))
- .filter("@".concat(avgprice).concat(">=2"))
- .sortBy(Integer.MAX_VALUE, SortedField.asc("@".concat(state)));
- return client.aggregate(builder);
- }
-
- private static Map<String, Object> createDocument(String storeName, String storeIntroduce,
- String tag, GeoValue location, Integer start){
-
- Map<String, Object> fields = new HashMap<>();
-
- fields.put("storeName", storeName);
- fields.put("storeIntroduce", storeIntroduce);
- fields.put("tag", tag);
- fields.put("location", location);
- fields.put("start", start);
-
- return fields;
- }
-
- public static void show(SearchResult searchResult){
- // 输出
- searchResult.docs.stream().forEach(System.out::println);
- }
- }

测试类
- @SpringBootTest
- class RedisSearchApplicationTests {
-
- @Autowired
- private RedisSearchUtilsV2 redisSearchUtilsV2;
-
- @Autowired
- private RedisSearchUtils redisSearchUtils;
-
- @Test
- void drop(){
- // 删除索引
- redisSearchUtilsV2.dropIndex();
- }
-
- @Test
- void test(){
- // 添加数据
- redisSearchUtilsV2.addHashData();
- }
-
- // 全文搜索
- @Test
- void Test1() {
- // 根据key查询数据
- redisSearchUtilsV2.searchByKey("家居");
- }
-
- // key+number范围查询
- @Test
- void test3(){
- // 查询包含内容家居,字段"start"值在100~400的数据
- redisSearchUtilsV2.searchByNumberRange("家居","start",100,400);
- }
-
- // 搜索某一经纬度点,半径5000m范围内的数据
- @Test
- void test4(){
- redisSearchUtilsV2.searchByGeoRange("家居",106.555697,29.613248,5000, "m");
- }
-
- }

查询效果
接下来学习redisearch+redisJSON结合使用(这种方式的效率更高)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。