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

Spring Boot + MeiliSearch 快速整合指南

開發 前端
在數據檢索需求日益增長的當下,傳統數據庫的查詢方式在復雜搜索場景下逐漸顯得力不從心,而MeiliSearch作為一款輕量級、高性能的開源搜索引擎,憑借其簡單易用的API和出色的搜索性能脫穎而出。

前言

在數據檢索需求日益增長的當下,傳統數據庫的查詢方式在復雜搜索場景下逐漸顯得力不從心,而MeiliSearch作為一款輕量級、高性能的開源搜索引擎,憑借其簡單易用的API和出色的搜索性能脫穎而出。

MeiliSearch 簡介

MeiliSearch 是一個用 Rust 編寫的輕量級、實時、開源搜索引擎,具有以下特點:

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

安裝

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

圖片圖片

把下載后的文件meilisearch-linux-amd64放置在meilisearch目錄中,同時給上可執行權限。

在meilisearch目錄下,創建配置文件 config.toml,參考以下內容:

# development or production,表示開發或生產環境,線上記得使用生產環境
env = "development"

# api訪問的master_key 
master_key = "yianweilai"

# http api 啟動的IP和端口
http_addr = "0.0.0.0:7700"

# 數據文件所在目錄
db_path = "./data"

dump_dir = "./dumps"

snapshot_dir = "./snapshots"

# 日志等級
log_level = "INFO"

啟動測試:./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,在此處填寫,若無則留空

創建 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);
    }
}

基本操作實現

/**
 * MeiliSearch 基本操作實現
 */
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()) {
            //判斷是否存在這個注解
            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> {
}

測試

@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()));
    }
}

圖片圖片

圖片 圖片

責任編輯:武曉燕 來源: 一安未來
相關推薦

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

2017-04-17 10:35:40

Spring BooRedis 操作

2017-10-17 15:14:33

Spring BooThymeleafWeb

2022-07-11 09:36:38

SpringJava開發

2020-07-14 11:00:12

Spring BootRedisJava

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

2024-03-26 08:08:08

SpringBPMN模型

2022-07-27 10:39:14

Spring代碼IDEA

2022-05-06 10:42:09

JavaFlowable引擎

2024-01-16 08:17:29

Mybatis驗證業務

2022-05-18 12:04:19

Mybatis數據源Spring

2025-03-26 03:25:00

SpringGuavaCaffeine

2020-07-02 15:40:11

Spring BootJar包Java

2024-10-15 09:34:57

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 羞羞视频网页 | 久久九九免费 | 国产精品久久久爽爽爽麻豆色哟哟 | 伊人成人免费视频 | 亚洲国产情侣自拍 | 欧美人妇做爰xxxⅹ性高电影 | www.亚洲 | 天天精品在线 | 欧美一区二区二区 | 国产福利一区二区 | 91久久看片 | 亚洲精品一区二区三区蜜桃久 | 亚洲欧美综合 | 成人国产精品久久久 | 欧美一区二区三区 | 国产欧美精品一区二区色综合朱莉 | 欧美一区二区另类 | 亚洲精品一二区 | 91资源在线 | 国产精品久久久久久一区二区三区 | 中国美女撒尿txxxxx视频 | 一区二区三区国产 | 久久精品国产亚洲 | 日韩亚洲视频 | 精品伊人| 欧美成年人网站 | 精品欧美一区二区三区久久久小说 | www.婷婷亚洲基地 | 日韩欧美中文在线 | 精品国产欧美一区二区三区成人 | 日韩欧美在线视频 | 国产成人av在线播放 | 国产精品视频在线观看 | 99re国产视频 | 久久伊人免费视频 | 午夜精品久久久 | 狠狠的操 | 一区二区三区欧美 | 天堂男人av | 99久久久久久 | 国产yw851.c免费观看网站 |