实战我的项目地址newbeemall,集成RediSearch,代码开源已上传,反对的话能够点个star

RediSearch 是基于 Redis 开发的反对二级索引、查问引擎和全文搜寻的应用程序。在2.0的版本中,简略看下官网测试报告:

索引构建

在索引构建测试中,RediSearch 用221秒的速度超过了 Elasticsearch的349秒,当先58%,

查问性能

数据集建设索引后,咱们应用运行在专用负载生成器服务器上的 32 个客户端启动了两个词的搜寻查问。如下图所示,RediSearch 的吞吐量达到了 12.5K ops/sec,而 Elasticsearch 的吞吐量达到了 3.1K ops/sec,快了 4 倍。此外,RediSearch 的提早稍好一些,均匀为 8 毫秒,而 Elasticsearch 为 10 毫秒。
(ops/sec每秒操作数)

由此可见,新的RediSearch在性能上比照RediSearch较有劣势,此外对中文我的项目来说对于中文的反对必不可少,RediSearch也在官网文档特意列出了反对中文,基于frisoC语言开发的中文分词我的项目。

一、RediSearch装置

Docker装置最新版

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

通过redis-cli连贯查看RediSearch是否装置胜利

1、redis-cli -h localhost 2、module list82.157.141.70:16789> MODULE LIST     1) 1) "name"       2) "search" # 查看是否蕴含search模块       3) "ver"       4) (integer) 20210    2) 1) "name"       2) "ReJSON" # 查看是否蕴含ReJSON模块       3) "ver"       4) (integer) 20007

二、客户端集成

对于Java我的项目间接选用Jedis4.0版本就能够,Jedis在4.0版本主动反对RediSearch,编写Jedis连贯RedisSearch测试用例,用RedisSearch命令创立如下:

FT.CREATE idx:goods on hash prefix 1 "goods:" language chinese schema goodsName text sortable// FT.CREATE 创立索引命令// idx:goods 索引名称// on hash 索引数据基于hash类型源数据构建// prefix 1 "goods:" 示意要创立索引的源数据前缀匹配规定// language chinese 示意反对中文语言分词// schema 示意字段定义,goodsName元数据属性名 text字段类型 sortable自持排序FT.INFO idx:goods // FT.INFO 查问指定名称索引信息FT.DROPINDEX idx:goods // FT.DROPINDEX 删除指定名称索引,不会删除源数据增加索引时,应用hset命令增加索引源数据删除索引时,应用del命令删除索引源数据
  1. Jedis创立RediSearch客户端

    @Beanpublic UnifiedJedis unifiedJedis(GenericObjectPoolConfig jedisPoolConfig) { UnifiedJedis client; if (StringUtils.isNotEmpty(password)) {     client = new JedisPooled(jedisPoolConfig, host, port, timeout, password, database); } else {     client = new JedisPooled(jedisPoolConfig, host, port, timeout, null, database); } return client;}
  2. Jedis创立索引

    @Testpublic void createIndex() { System.out.println("begin"); Schema schema = new Schema()         .addSortableTextField("goodsName", 1.0)         .addSortableTextField("goodsIntro", 0.5)         .addSortableTagField("tag", "|"); jedisSearch.createIndex(idxName, "goods", schema); System.out.println("end");}/** * 创立索引 * * @param idxName 索引名称 * @param prefix  要索引的数据前缀 * @param schema  索引字段配置 */public void createIndex(String idxName, String prefix, Schema schema) { IndexDefinition rule = new IndexDefinition(IndexDefinition.Type.HASH)         .setPrefixes(prefix)         .setLanguage(Constants.GOODS_IDX_LANGUAGE); # 设置反对中文分词 client.ftCreate(idxName,         IndexOptions.defaultOptions().setDefinition(rule),         schema);}
  3. Jedis增加索引源数据

    /** * 增加索引数据 * * @param keyPrefix 要索引的数据前缀 * @param goods     商品信息 * @return boolean */public boolean addGoodsIndex(String keyPrefix, Goods goods) { Map<String, String> hash = MyBeanUtil.toMap(goods); hash.put("_language", Constants.GOODS_IDX_LANGUAGE); client.hset(keyPrefix + goods.getGoodsId(), MyBeanUtil.toMap(goods)); return true;}
  4. Jedis中文查问

    public SearchResult search(String goodsIdxName, SearchObjVO searchObjVO,     Page<SearchPageGoodsVO> page) { String keyword = searchObjVO.getKeyword(); // 查问关键字 String queryKey = String.format("@goodsName:(%s)", keyword); Query q = new Query(queryKey); String sort = searchObjVO.getSidx(); String order = searchObjVO.getOrder(); // 查问是否排序 if (StringUtils.isNotBlank(sort)) {     q.setSortBy(sort, Constants.SORT_ASC.equals(order)); } // 设置中文分词查问 q.setLanguage(Constants.GOODS_IDX_LANGUAGE); // 查问分页 q.limit((int) page.offset(), (int) page.getSize()); // 返回查问后果 return client.ftSearch(goodsIdxName, q);}

三、我的项目实战

  1. 引入Jedis4.0

    <jedis.version>4.2.0</jedis.version><!-- jedis --><dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version></dependency>
  2. 在newbeemall我的项目后盾商品治理中增加同步按钮

编写商品全量同步按钮,为了放慢同步速度,通过多线程同步

// 同步商品到RediSearchpublic boolean syncRs() {    jedisSearch.dropIndex(Constants.GOODS_IDX_NAME);    Schema schema = new Schema()            .addSortableTextField("goodsName", 1.0)            .addSortableTextField("goodsIntro", 0.5)            .addSortableNumericField("goodsId")            .addSortableNumericField("sellingPrice")            .addSortableNumericField("originalPrice")            .addSortableTagField("tag", "|");    jedisSearch.createIndex(Constants.GOODS_IDX_NAME, "goods:", schema);    List<Goods> list = this.list();    jedisSearch.deleteGoodsList(Constants.GOODS_IDX_PREFIX);    return jedisSearch.addGoodsListIndex(Constants.GOODS_IDX_PREFIX, list);}/** * 同步商品索引 * * @param keyPrefix 要索引的数据前缀 * @return boolean */public boolean addGoodsListIndex(String keyPrefix, List<Goods> list) {    int chunk = 200;    int size = list.size();    int ceil = (int) Math.ceil(size / (double) chunk);    // 多线程同步    List<CompletableFuture<Void>> futures = new ArrayList<>(4);    for (int i = 0; i < ceil; i++) {        int toIndex = (i + 1) * chunk;        if (toIndex > size) {            toIndex = i * chunk + size % chunk;        }        List<Goods> subList = list.subList(i * chunk, toIndex);        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> subList).thenAccept(goodsList -> {            for (Goods goods : goodsList) {                Map<String, String> hash = MyBeanUtil.toMap(goods);                hash.put("_language", Constants.GOODS_IDX_LANGUAGE);                client.hset(keyPrefix + goods.getGoodsId(), MyBeanUtil.toMap(goods));            }        });        futures.add(voidCompletableFuture);    }    CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();    return true;}
  1. 批改商品页面搜寻接口

    @GetMapping("/search")public String rsRearch(SearchObjVO searchObjVO, HttpServletRequest request) { Page<SearchPageGoodsVO> page = getPage(request, Constants.GOODS_SEARCH_PAGE_LIMIT); ... // RediSearch中文搜索 SearchResult query = jedisSearch.search(Constants.GOODS_IDX_NAME, searchObjVO, page); ... return "mall/search";}
  2. 查看搜寻后果中蕴含"小米"、"手机"两个独自分词

四、总结

通过以上实战我的项目,应用RediSearch是能够满足根本中文分词需要

高级用法聚合查问、后果高亮、停用词、扩大API、拼写更正、主动补全等能够在官网理解。
最初贴一下实战我的项目地址newbeemall,集成RediSearch,代码开源已上传