成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot + MeiliSearch 快速整合指南

開發(fā) 前端
在數(shù)據(jù)檢索需求日益增長(zhǎng)的當(dāng)下,傳統(tǒng)數(shù)據(jù)庫(kù)的查詢方式在復(fù)雜搜索場(chǎng)景下逐漸顯得力不從心,而MeiliSearch作為一款輕量級(jí)、高性能的開源搜索引擎,憑借其簡(jiǎn)單易用的API和出色的搜索性能脫穎而出。

前言

在數(shù)據(jù)檢索需求日益增長(zhǎng)的當(dāng)下,傳統(tǒng)數(shù)據(jù)庫(kù)的查詢方式在復(fù)雜搜索場(chǎng)景下逐漸顯得力不從心,而MeiliSearch作為一款輕量級(jí)、高性能的開源搜索引擎,憑借其簡(jiǎn)單易用的API和出色的搜索性能脫穎而出。

MeiliSearch 簡(jiǎn)介

MeiliSearch 是一個(gè)用 Rust 編寫的輕量級(jí)、實(shí)時(shí)、開源搜索引擎,具有以下特點(diǎn):

  • 快速部署:可通過二進(jìn)制文件或Docker快速啟動(dòng)。
  • 實(shí)時(shí)更新:數(shù)據(jù)的添加、更新和刪除操作能即時(shí)反映在搜索結(jié)果中。
  • 簡(jiǎn)單易用:提供簡(jiǎn)潔的HTTP API,方便與各種編程語(yǔ)言集成。
  • 強(qiáng)大的搜索功能:支持關(guān)鍵詞高亮、模糊搜索、分面搜索等高級(jí)功能。

安裝

選擇自己的版本https://github.com/meilisearch/meilisearch/tags:

圖片圖片

把下載后的文件meilisearch-linux-amd64放置在meilisearch目錄中,同時(shí)給上可執(zhí)行權(quán)限。

在meilisearch目錄下,創(chuàng)建配置文件 config.toml,參考以下內(nèi)容:

# development or production,表示開發(fā)或生產(chǎn)環(huán)境,線上記得使用生產(chǎn)環(huán)境
env = "development"

# api訪問的master_key 
master_key = "yianweilai"

# http api 啟動(dòng)的IP和端口
http_addr = "0.0.0.0:7700"

# 數(shù)據(jù)文件所在目錄
db_path = "./data"

dump_dir = "./dumps"

snapshot_dir = "./snapshots"

# 日志等級(jí)
log_level = "INFO"

啟動(dòng)測(cè)試:./meilisearch-linux-amd64 --config-file-path=./config.toml

圖片圖片

訪問http管理界面:

圖片圖片

如何使用

添加 MeiliSearch 依賴

<!-- https://mvnrepository.com/artifact/com.meilisearch.sdk/meilisearch-java -->
<dependency>
    <groupId>com.meilisearch.sdk</groupId>
    <artifactId>meilisearch-java</artifactId>
    <version>0.14.2</version>
</dependency>

配置 MeiliSearch

meilisearch:
  host: http://172.18.2.73:7700
  api-key: yianweilai  # 如果MeiliSearch配置了API Key,在此處填寫,若無(wú)則留空

創(chuàng)建 MeiliSearch 配置類

@Configuration
public class MeiliSearchConfig {

    @Value("${meilisearch.host:}")
    private String host;

    @Value("${meilisearch.api-key:}")
    private String apiKey;

    @Bean
    public Client meiliSearchClient() {
        Config config = new Config(host, apiKey);
        return new Client(config);
    }
}

基本操作實(shí)現(xiàn)

/**
 * MeiliSearch 基本操作實(shí)現(xiàn)
 */
public class MeilisearchRepository<T> implements InitializingBean, DocumentOperations<T> {

    private Index index;
    private Class<T> tClass;
    private JsonHandler jsonHandler = new JsonHandler();

    @Resource
    private Client client;


    @Override
    public T get(String identifier) {
        T document;
        try {
            document = index.getDocument(identifier, tClass);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return document;
    }

    @Override
    public List<T> list() {
        List<T> documents;
        try {
            documents = Optional.ofNullable(index.getDocuments(tClass))
                    .map(indexDocument -> indexDocument.getResults())
                    .map(result -> Arrays.asList(result))
                    .orElse(new ArrayList<>());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return documents;
    }

    @Override
    public List<T> list(int limit) {
        List<T> documents;
        try {
            DocumentsQuery query = new DocumentsQuery();
            query.setLimit(limit);
            documents = Optional.ofNullable(index.getDocuments(query, tClass))
                    .map(indexDocument -> indexDocument.getResults())
                    .map(result -> Arrays.asList(result))
                    .orElse(new ArrayList<>());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return documents;
    }

    @Override
    public List<T> list(int offset, int limit) {
        List<T> documents;
        try {
            DocumentsQuery query = new DocumentsQuery();
            query.setLimit(limit);
            query.setOffset(offset);
            documents = Optional.ofNullable(index.getDocuments(query, tClass))
                    .map(indexDocument -> indexDocument.getResults())
                    .map(result -> Arrays.asList(result))
                    .orElse(new ArrayList<>());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return documents;
    }

    @Override
    public long add(T document) {
        List<T> list = Collections.singletonList(document);
        return add(list);
    }

    @Override
    public long update(T document) {
        List<T> list = Collections.singletonList(document);
        return update(list);
    }

    @Override
    public long add(List documents) {
        int taskId;
        try {
            taskId = index.addDocuments(JSON.toJSONString(documents)).getTaskUid();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return taskId;
    }

    @Override
    public long update(List documents) {
        int updates;
        try {
            updates = index.updateDocuments(JSON.toJSONString(documents)).getTaskUid();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return updates;
    }


    @Override
    public long delete(String identifier) {
        int taskId;
        try {
            taskId = index.deleteDocument(identifier).getTaskUid();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return taskId;
    }

    @Override
    public long deleteBatch(String... documentsIdentifiers) {
        int taskId;
        try {
            taskId = index.deleteDocuments(Arrays.asList(documentsIdentifiers)).getTaskUid();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return taskId;
    }

    @Override
    public long deleteAll() {
        int taskId;
        try {
            taskId = index.deleteAllDocuments().getTaskUid();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return taskId;
    }


    @Override
    public SearchResult<T> search(String q) {
        String result;
        try {
            result = JSON.toJSONString(index.search(q));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return jsonHandler.resultDecode(result, tClass);
    }

    @Override
    public SearchResult<T> search(String q, int offset, int limit) {
        SearchRequest searchRequest = SearchRequest.builder().build();
        searchRequest.setQ(q);
        searchRequest.setOffset(offset);
        searchRequest.setLimit(limit);
        return search(searchRequest);
    }

    @Override
    public SearchResult<T> search(SearchRequest sr) {
        String result;
        try {
            result = JSON.toJSONString(index.search(sr));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return jsonHandler.resultDecode(result, tClass);
    }

    @Override
    public String select(SearchRequest sr) {
        try {
            if (ObjectUtil.isNotNull(sr)) {
                if (ObjectUtil.isNull(getIndex())) {
                    initIndex();
                }
                Searchable search = getIndex().search(sr);
                String jsonString = JSON.toJSONString(search);
                return jsonString;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public Settings getSettings() {
        try {
            return index.getSettings();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public TaskInfo updateSettings(Settings settings) {
        try {
            return index.updateSettings(settings);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public TaskInfo resetSettings() {
        try {
            return index.resetSettings();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Task getUpdate(int updateId) {
        try {
            return index.getTask(updateId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initIndex();
    }

    public Index getIndex() {
        return index;
    }

    /**
     * 初始化索引信息
     *
     * @throws Exception
     */
    private void initIndex() throws Exception {
        Class<? extends MeilisearchRepository> clazz = getClass();
        tClass = (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
        MSIndex annoIndex = tClass.getAnnotation(MSIndex.class);
        String uid = annoIndex.uid();
        String primaryKey = annoIndex.primaryKey();
        if (StringUtils.isEmpty(uid)) {
            uid = tClass.getSimpleName().toLowerCase();
        }
        if (StringUtils.isEmpty(primaryKey)) {
            primaryKey = "id";
        }
        int maxTotalHit=1000;
        int maxValuesPerFacet=100;
        if (Objects.nonNull(annoIndex.maxTotalHits())){
            maxTotalHit=annoIndex.maxTotalHits();
        }
        if (Objects.nonNull(annoIndex.maxValuesPerFacet())){
            maxValuesPerFacet=100;
        }

        List<String> filterKey = new ArrayList<>();
        List<String> sortKey = new ArrayList<>();
        List<String> noDisPlay = new ArrayList<>();
        //獲取類所有屬性
        for (Field field : tClass.getDeclaredFields()) {
            //判斷是否存在這個(gè)注解
            if (field.isAnnotationPresent(MSFiled.class)) {
                MSFiled annotation = field.getAnnotation(MSFiled.class);
                if (annotation.openFilter()) {
                    filterKey.add(annotation.key());
                }

                if (annotation.openSort()) {
                    sortKey.add(annotation.key());
                }
                if (annotation.noDisplayed()) {
                    noDisPlay.add(annotation.key());
                }
            }
        }
        Results<Index> indexes = client.getIndexes();
        Index[] results = indexes.getResults();
        Boolean isHaveIndex=false;
        for (Index result : results) {
            if (uid.equals(result.getUid())){
                isHaveIndex=true;
                break;
            }
        }

        if (isHaveIndex){
            client.updateIndex(uid,primaryKey);
        }else {
            client.createIndex(uid, primaryKey);
        }
        this.index = client.getIndex(uid);
        Settings settings = new Settings();
        settings.setDisplayedAttributes(noDisPlay.size()>0?noDisPlay.toArray(new String[noDisPlay.size()]):new String[]{"*"});
        settings.setFilterableAttributes(filterKey.toArray(new String[filterKey.size()]));
        settings.setSortableAttributes(sortKey.toArray(new String[sortKey.size()]));
        index.updateSettings(settings);
    }
}

以Demo為例

@Repository
public class MeiliSearchMapper extends MeilisearchRepository<DemoDO> {
}

測(cè)試

@Slf4j
@SpringBootTest
public class TestDemo {

    @Autowired
    private MeiliSearchMapper meiliSearchMapper;


    @Test
    public void test1(){
        meiliSearchMapper.add(new DemoDO(1,"yian1","beijing1","yian1@yian.com","https://images.pexels.com/photos/3866556/pexels-photo-3866556.png",
                System.currentTimeMillis(),System.currentTimeMillis()));
        meiliSearchMapper.add(new DemoDO(2,"yian2","beijing2","yian2@yian.com","https://images.pexels.com/photos/19184114/pexels-photo-19184114.jpeg",
                System.currentTimeMillis(),System.currentTimeMillis()));
        meiliSearchMapper.add(new DemoDO(3,"yian3","beijing3","yian3@yian.com","https://images.pexels.com/photos/6310172/pexels-photo-6310172.jpeg",
                System.currentTimeMillis(),System.currentTimeMillis()));
    }

    @Test
    public void test2(){
        StringBuffer sb = new StringBuffer();
        StringBuffer demo = sb.append("name=yian1").append(" AND ").append("addr=beijing1");
        SearchRequest searchRequest = SearchRequest.builder().build()
                .setFilter(new String[]{demo.toString()})
                .setLimit(10);
        SearchResult<DemoDO> search = meiliSearchMapper.search(searchRequest);
        log.info("{}",search);
    }

    @Test
    public void test3(){
        meiliSearchMapper.deleteAll();
    }

    @Test
    public void test4(){
        meiliSearchMapper.update(new DemoDO(1,"yian1","beijing1","yian1@yian.com","https://images.pexels.com/photos/3866556/pexels-photo-3866556.png",
                System.currentTimeMillis(),System.currentTimeMillis()));
    }
}

圖片圖片

圖片 圖片

責(zé)任編輯:武曉燕 來(lái)源: 一安未來(lái)
相關(guān)推薦

2025-07-02 07:33:02

Spring倒排索引分布式

2022-07-21 11:04:53

Swagger3Spring

2022-12-23 08:28:42

策略模式算法

2022-06-28 15:04:32

容器Docker

2022-06-28 15:06:35

容器Spring

2022-07-11 09:36:38

SpringJava開發(fā)

2020-07-14 11:00:12

Spring BootRedisJava

2017-10-17 15:14:33

Spring BooThymeleafWeb

2017-04-17 10:35:40

Spring BooRedis 操作

2022-03-07 09:00:00

HTTPS證書中間件

2020-09-02 17:28:26

Spring Boot Redis集成

2024-09-27 08:25:47

2020-12-01 08:32:12

Spring Boot

2022-07-27 10:39:14

Spring代碼IDEA

2024-03-26 08:08:08

SpringBPMN模型

2025-06-27 02:44:00

2022-05-06 10:42:09

JavaFlowable引擎

2024-01-16 08:17:29

Mybatis驗(yàn)證業(yè)務(wù)

2020-07-02 15:40:11

Spring BootJar包Java

2024-10-15 09:34:57

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91在线电影| aa级毛片毛片免费观看久 | 国产三区四区 | 日本一道本视频 | 一区二区三区视频在线免费观看 | 99热在线免费 | 亚洲最新网址 | 黄网站免费观看 | 久久99精品久久久久久青青日本 | 日韩在线免费播放 | 成人精品在线观看 | 99久久免费精品国产男女高不卡 | 久久日韩精品 | 欧美一区二区三区视频在线播放 | 综合久久久久 | 国产日韩精品久久 | 超碰伊人久久 | 中文字幕国产精品视频 | 极品国产视频 | 精品影院 | 一级黄色录像片子 | 国产精品av久久久久久毛片 | 午夜视频一区 | 亚洲色图在线观看 | 日韩一区二区不卡 | 国产成人叼嘿视频在线观看 | 亚洲欧美日韩中文在线 | 欧美日韩在线高清 | 亚洲一区二区在线播放 | 九九色综合 | 国产超碰人人爽人人做人人爱 | 国产一区二区在线免费观看 | 亚洲欧美在线视频 | 亚洲精品一区二区三区中文字幕 | 国产精品波多野结衣 | 中文字幕欧美在线观看 | 欧美在线激情 | 美女黄色在线观看 | 久久久久91 | 欧美国产视频 | 91在线精品秘密一区二区 |