自定义查询-

最近学习了es的视频,感觉这个产品对于查询来说非常方便,但是如何应用到我们自己的 产品中来呢。因为我们的产品数据更新太快,其实不太适合用es做主力存储。并且我们的业务还没有到那种巨量级别,产品的服务器容量也有限,所以我打算根据es的倒排索引的原理,自己写一个查询的组件。

我的理解是这样的,有大量的文字需要进行模糊查询,在mysql中,如果使用like的话是非常合适的,目前我就是采用这种方式查询的,因为数据量还未到千万级别,速度也还行,不过马上要突破了,所以要考虑优化的事情了。所以我的思路是这样的:

1 首先将数据库中的大段文字和标题都提取出来。

2 这些文字都对应了主键。

3 使用jcseg分词将一段文字进行分词,然后将分好的词语主键保存到redis中去。

4 为了节省空间,只分重要的业务关键字,其他无关的分词都不需要。

5 因为数据量巨大,在进行数据提取的时候,采用了线程池,优化了采集速度。

 

使用的代码如下:

package com.liandyao.caop.caopdata.service.impl.ESearch;

import cn.hutool.core.util.StrUtil;
import com.liandyao.caop.caopdata.entity.CaiCaop;
import com.liandyao.caop.caopdata.mapper.CaiMapper;
import com.liandyao.caop.utils.ChineseSegment;
import com.liandyao.caop.utils.async.AsyncManager;
import com.liandyao.caop.utils.redis.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 倒排索引的研究
 * @author liandyao
 * @date 2022年6月24日
 */
@Service
public class CaiInvertedIndex {

    /**
     * 原子类型的数字
     */
    public static AtomicInteger atomic = new AtomicInteger();


    /**
     * 每页查询多少条
     */
    public static int SIZE = 1000 ;

    /**
     * KEY
     */
    public static String REDIS_KEY = "INVD_INDX:MYSQL_DATA:CAOPU";

    @Autowired
    CaipMapper caopMapper;

    @Autowired
    RedisUtil redisUtil ;

    /**
     * 同步数据到redis
     */
    @Transactional
    public void sysnCaopDataToRedis(int pages){
        System.out.println(pages);
        //每页显示1000条

        int startRows = (pages - 1) * SIZE ;
        List<CaiCaop> listCaop =caopMapper.selectListByPage(startRows,SIZE);

        System.out.println("查询的条数:"+listCaop.size());
        listCaop.forEach(caop->{
            //加入到redis中
            redisUtil.leftPush(REDIS_KEY,caop);
            //最后一个执行的id,因为多线程的原因可能不是最后一个,这里只是记录一下
            redisUtil.set(REDIS_KEY+"LAST_ID",caop.getId());
        });
    }

    /**
     * 加入分词信息
     */
    public void segCaopData(){
        long caopSize = redisUtil.lGetListSize(REDIS_KEY);
        System.out.println("正在处理,共有:"+caopSize+"条数据");
        int i = 0;
        while(i<caopSize){
            //运行一次增加1
            i++;
            AsyncManager.me().execute(new TimerTask() {
                @Override
                public void run() {
                    CaiCaop caop = (CaiCaop) redisUtil.rightPop(REDIS_KEY);
                    if(caop!=null){
                        String content = caop.getContent()+" "+caop.getAddress();
                        List<String> typeNames = StrUtil.split(caop.getTypeName(),",");

                        //先将种类作为倒序索引加入redis
                        typeNames.forEach(str->{
                            if(StrUtil.isNotBlank(str)){
                                redisUtil.zsetAdd(REDIS_KEY+":"+str,caop.getId(),caop.getUpdateDate().getTime());
                            }

                        });
                        //再进行分词
                        List<String> list = ChineseSegment.segment(content);
                        list.forEach(segWord->{
                            redisUtil.zsetAdd(REDIS_KEY+":"+segWord,caop.getId(),caop.getUpdateDate().getTime());
                        });
                        System.out.println("处理成功:"+caop.getId());
                    }
                }
            });
        }



    }


    public static void main(String[] args) {


    }

}
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 自定义查询-