当前位置:   article > 正文

redisearch+springboot的简单使用_redisearch springboot

redisearch springboot

安装

推荐使用docker安装,使用以下命令即可安装并启动redisearch

docker run -p 6379:6379 redislabs/redisearch:latest

通过下载redisearch二进制文件,将二进制文件加载进redis模块的方式好像对于开源的redis版本不能使用 ,要商业版的才可以。(因为我使用开源redis用了一天,就提示我不能使用了)

使用RediSearch来搜索数据之前,我们得先创建下索引: 

  1. FT.CREATE {index}
  2. [ON {data_type}]
  3. [PREFIX {count} {prefix} [{prefix} ..]
  4. [LANGUAGE {default_lang}]
  5. SCHEMA {identifier} [AS {attribute}]
  6. [TEXT | NUMERIC | GEO | TAG ] [CASESENSITIVE]
  7. [SORTABLE] [NOINDEX]] ...
  • 使用FT.CREATE命令可以建立索引,语法中的参数意义如下;
    • index:索引名称;
    • data_type:建立索引的数据类型,目前支持JSON或者HASH两种;
    • PREFIX:通过它可以给索引加上前缀
    • LANGUAGE:指定TEXT类型属性的默认语言,使用chinese可以设置为中文;
    • identifier:指定属性名称;
    • attribute:指定属性别名;
    • TEXT | NUMERIC | GEO | TAG:这些都是属性可选的类型;
    • SORTABLE:指定属性可以进行排序。

看一下官方文档是怎么使用的https://redis.io/docs/stack/search/quick_start/

创建索引

使用FT.CREATE命令创建具有字段和权重的索引(默认权重为 1.0):

  • 创建索引myIdx
  • 索引类型为hash
  • 索引加上前缀doc:
  • 字段title,数据类型:text;weight  5.0 权重
  • 字段body,url,数据类型:text;
  1. 127.0.0.1:6379> FT.CREATE myIdx ON HASH PREFIX 1 doc: SCHEMA title TEXT WEIGHT 5.0 body TEXT url TEXT
  2. OK

此时,任何带有前缀的键的现有哈希文档都会doc:自动添加到索引中。

添加文件

创建索引后,任何带有doc:前缀的新哈希文档都会在创建时自动建立索引。

使用HSET命令创建一个新的哈希文档并将其添加到索引中:

  1. 127.0.0.1:6379> HSET doc:1 title "hello world" body "lorem ipsum" url "http://redis.io"
  2. (integer) 3

搜索索引

要在索引中搜索包含特定单词的文档,请使用以下FT.SEARCH命令:

  1. 127.0.0.1:6379> FT.SEARCH myIdx "hello world" LIMIT 0 10
  2. 1) (integer) 1
  3. 2) "doc:1"
  4. 3) 1) "title"
  5. 2) "hello world"
  6. 3) "body"
  7. 4) "lorem ipsum"
  8. 5) "url"
  9. 6) "http://redis.io"

删除索引

要删除索引而不删除关联的哈希文档

  1. 127.0.0.1:6379> FT.DROPINDEX myIdx
  2. OK

更多命令使用还可以看看这篇文章https://zhuanlan.zhihu.com/p/478548947

用javaAPI的方式使用redisearch(索引类型使用的是hash)

导入maven坐标

  1. <dependency>
  2. <groupId>com.redislabs</groupId>
  3. <artifactId>jredisearch</artifactId>
  4. <version>1.8.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>cn.hutool</groupId>
  8. <artifactId>hutool-all</artifactId>
  9. <version>5.3.10</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.hankcs</groupId>
  13. <artifactId>hanlp</artifactId>
  14. <version>portable-1.7.8</version>
  15. </dependency>

配置类,注入Client对象

  1. @Configuration
  2. public class RSclientConfig {
  3. @Bean
  4. public Client setClient(){
  5. /*
  6. Client 是主要的 RediSearch 客户端类,包装了连接管理和所有 RediSearch 命令
  7. 连接redisearch
  8. "store"索引(相当于表)
  9. */
  10. Client client = new Client("store", host, port);
  11. return client;
  12. }
  13. }

rediSearch工具类

  1. import io.redisearch.*;
  2. import io.redisearch.aggregation.AggregationBuilder;
  3. import io.redisearch.aggregation.SortedField;
  4. import io.redisearch.aggregation.reducers.Reducers;
  5. import io.redisearch.client.AddOptions;
  6. import io.redisearch.client.Client;
  7. import io.redisearch.querybuilder.GeoValue;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Component;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. @Slf4j
  14. @Component
  15. public class RedisSearchUtilsV2 {
  16. @Autowired
  17. private Client client;
  18. /**
  19. * 删除索引
  20. */
  21. public void dropIndex(){
  22. // 只会删除索引,不会删除索引相关的文档,true:表示如果索引不存在,直接返回false,不报错
  23. client.dropIndex(true);
  24. }
  25. /**
  26. * 删除文档数据
  27. */
  28. public void deleteDocuments(String ...docs){
  29. // 传入一组(将删除的文档ID)
  30. client.deleteDocuments(true,docs);
  31. }
  32. /**修改文档**/
  33. public void updateDocument(String docId, double score, Map map){
  34. client.updateDocument(docId,score,map);
  35. }
  36. /**添加数据8**/
  37. public boolean addHashData(){
  38. try{
  39. // FullText类型(全文查询)
  40. Schema.Field storeName = new Schema.Field("storeName", Schema.FieldType.FullText,false);
  41. Schema.Field storeIntroduce = new Schema.Field("storeIntroduce", Schema.FieldType.FullText,false);
  42. // tag类型
  43. Schema.Field tag = new Schema.Field("tag", Schema.FieldType.Tag,false);
  44. // geo类型,经纬度
  45. Schema.Field location = new Schema.Field("location", Schema.FieldType.Geo,false);
  46. // number类型(此类型可以范围查询),true:允许排序
  47. Schema.Field start = new Schema.Field("start", Schema.FieldType.Numeric,true);
  48. // 定义一个索引模式(相当于student的表结构)
  49. Schema schema = new Schema()
  50. .addField(storeName)
  51. .addField(storeIntroduce)
  52. .addField(tag)
  53. //.addField(location)// 加上Geo类型后,无法查询出数据,暂时不知道什么原因
  54. .addField(start);
  55. // 创建索引(如果存在相同的索引则会创建失败)
  56. client.createIndex(schema, Client.IndexOptions.Default());
  57. // 创建一些map数据,准备存入student索引
  58. Map<String, Object> fields1 = createDocument("粥铺", "我家小米粥好喝", "满减"
  59. ,new GeoValue(106.555697,29.613248,5000, GeoValue.Unit.METERS),300);
  60. Map<String, Object> fields2 = createDocument("米铺", "我家米便宜好吃", "香米"
  61. ,new GeoValue(106.555661,29.613695,100, GeoValue.Unit.METERS),100);
  62. Map<String, Object> fields3 = createDocument("米通信", "电子批发城", "电子"
  63. ,new GeoValue(106.555922,29.613429,100, GeoValue.Unit.METERS),120);
  64. Map<String, Object> fields4 = createDocument("熊猫家居", "只为让你有更好的舒适生活", "家居"
  65. ,new GeoValue(106.555922,29.613429,100, GeoValue.Unit.METERS),220);
  66. Map<String, Object> fields5 = createDocument("河马家居", "为你私人定制", "家居"
  67. ,new GeoValue(106.555571,29.612973,100, GeoValue.Unit.METERS),60);
  68. // 创建选项,设置语言为中文,否则无法进行中文分词查询
  69. AddOptions options = new AddOptions();
  70. options.setLanguage("chinese");
  71. /*
  72. 创建文档(相当于表的每一行数据)id:"doc1" fields:fields1 score:1
  73. id:唯一值,否则创建失败,且必须为string;
  74. fields:需要存放的数据(默认为Map类型);
  75. score:分数(权重0~1)
  76. */
  77. Document doc1 = new Document("doc1", fields1,1);
  78. Document doc2 = new Document("doc2", fields2,0.7);
  79. Document doc3 = new Document("doc3", fields3,0.5);
  80. Document doc4 = new Document("doc4", fields4,0.3);
  81. Document doc5 = new Document("doc5", fields5,0.1);
  82. // 添加文档,将设置项加进去
  83. client.addDocument(doc1,options);
  84. client.addDocument(doc2,options);
  85. client.addDocument(doc3,options);
  86. client.addDocument(doc4,options);
  87. client.addDocument(doc5,options);
  88. }catch (Exception e){
  89. e.printStackTrace();
  90. log.info("文档添加失败!");
  91. return false;
  92. }
  93. log.info("文档添加成功!");
  94. return true;
  95. }
  96. /**根据关键字全文查询
  97. * @method limit(0,3) 从位置0开始查询出3条
  98. * @method setWithScores() 按分数大小查询(权重),从大到小排
  99. * @method setLanguage("chinese") 默认不支持中文分词,所以要设置语言
  100. * @method highlightFields("title","body") 设置哪些字段需要高亮显示
  101. */
  102. public SearchResult searchByKey(String queryString) {
  103. // 创建查询语句
  104. Query query = new Query(queryString)
  105. .limit(0,3)
  106. .setWithScores()
  107. .highlightFields("storeName","storeIntroduce")
  108. .setLanguage("chinese");
  109. // 提交查询
  110. SearchResult result = client.search(query);
  111. // 输出
  112. show(result);
  113. return result;
  114. }
  115. /**根据数值范围+key查询
  116. *
  117. * @method addFilter()
  118. * 添加过滤器
  119. * @method Query.NumericFilter(field,min,max)
  120. * 数值过滤器
  121. * 查询字段field范围(min,max)
  122. * **/
  123. public SearchResult searchByNumberRange(String key, String field, int min, int max){
  124. Query query = new Query(key)
  125. .addFilter(new Query.NumericFilter(field,min,max))
  126. .limit(0,3)
  127. .setLanguage("chinese");
  128. // 提交查询
  129. SearchResult result = client.search(query);
  130. // 输出
  131. show(result);
  132. return result;
  133. }
  134. /**位置范围+key查询
  135. * new Query.GeoFilter("location",lon,lat,radius,unit)
  136. * 经纬度过滤器
  137. * @param key 搜索关键词
  138. * @param lon 经度
  139. * @param lat 纬度
  140. * @param radius 半径
  141. * @param unit 度量单位
  142. * **/
  143. public SearchResult searchByGeoRange(String key, double lon, double lat, double radius, String unit){
  144. Query query = new Query(key)
  145. .addFilter(new Query.GeoFilter("location",lon,lat,radius,unit))
  146. .limit(0,3)
  147. .setLanguage("chinese");
  148. // 提交查询
  149. SearchResult result = client.search(query);
  150. show(result);
  151. return result;
  152. }
  153. /**
  154. * 聚合查询
  155. * @param query
  156. * @param start
  157. * @param state
  158. * @param avgprice
  159. * @param k
  160. * @return
  161. */
  162. public AggregationResult aggregate(String query, String start, String state, String avgprice, String k){
  163. AggregationBuilder builder =new AggregationBuilder(query)
  164. .apply("@".concat(start).concat("/1000"), k)
  165. .groupBy("@".concat(state), Reducers.avg("@".concat(k)).as(avgprice))
  166. .filter("@".concat(avgprice).concat(">=2"))
  167. .sortBy(Integer.MAX_VALUE, SortedField.asc("@".concat(state)));
  168. return client.aggregate(builder);
  169. }
  170. private static Map<String, Object> createDocument(String storeName, String storeIntroduce,
  171. String tag, GeoValue location, Integer start){
  172. Map<String, Object> fields = new HashMap<>();
  173. fields.put("storeName", storeName);
  174. fields.put("storeIntroduce", storeIntroduce);
  175. fields.put("tag", tag);
  176. fields.put("location", location);
  177. fields.put("start", start);
  178. return fields;
  179. }
  180. public static void show(SearchResult searchResult){
  181. // 输出
  182. searchResult.docs.stream().forEach(System.out::println);
  183. }
  184. }

测试类

  1. @SpringBootTest
  2. class RedisSearchApplicationTests {
  3. @Autowired
  4. private RedisSearchUtilsV2 redisSearchUtilsV2;
  5. @Autowired
  6. private RedisSearchUtils redisSearchUtils;
  7. @Test
  8. void drop(){
  9. // 删除索引
  10. redisSearchUtilsV2.dropIndex();
  11. }
  12. @Test
  13. void test(){
  14. // 添加数据
  15. redisSearchUtilsV2.addHashData();
  16. }
  17. // 全文搜索
  18. @Test
  19. void Test1() {
  20. // 根据key查询数据
  21. redisSearchUtilsV2.searchByKey("家居");
  22. }
  23. // key+number范围查询
  24. @Test
  25. void test3(){
  26. // 查询包含内容家居,字段"start"值在100~400的数据
  27. redisSearchUtilsV2.searchByNumberRange("家居","start",100,400);
  28. }
  29. // 搜索某一经纬度点,半径5000m范围内的数据
  30. @Test
  31. void test4(){
  32. redisSearchUtilsV2.searchByGeoRange("家居",106.555697,29.613248,5000, "m");
  33. }
  34. }

查询效果

 接下来学习redisearch+redisJSON结合使用(这种方式的效率更高)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/853035
推荐阅读
相关标签
  

闽ICP备14008679号