偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Spring Boot + MeiliSearch 快速整合指南

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

前言

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

MeiliSearch 簡介

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

  • 快速部署:可通過二進(jìn)制文件或Docker快速啟動(dòng)。
  • 實(shí)時(shí)更新:數(shù)據(jù)的添加、更新和刪除操作能即時(shí)反映在搜索結(jié)果中。
  • 簡單易用:提供簡潔的HTTP API,方便與各種編程語言集成。
  • 強(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)測試:./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,在此處填寫,若無則留空

創(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> {
}

測試

@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é)任編輯:武曉燕 來源: 一安未來
相關(guān)推薦

2025-07-02 07:33:02

Spring倒排索引分布式

2022-07-21 11:04:53

Swagger3Spring

2022-12-23 08:28:42

策略模式算法

2017-04-17 10:35:40

Spring BooRedis 操作

2017-10-17 15:14:33

Spring BooThymeleafWeb

2020-07-14 11:00:12

Spring BootRedisJava

2022-07-11 09:36:38

SpringJava開發(fā)

2022-06-28 15:06:35

容器Spring

2022-06-28 15:04:32

容器Docker

2025-08-15 07:39:11

2020-12-01 08:32:12

Spring Boot

2025-10-13 07:56:07

2020-09-02 17:28:26

Spring Boot Redis集成

2024-09-27 08:25:47

2022-03-07 09:00:00

HTTPS證書中間件

2022-05-06 10:42:09

JavaFlowable引擎

2025-06-27 02:44:00

2024-03-26 08:08:08

SpringBPMN模型

2024-01-16 08:17:29

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

2022-07-27 10:39:14

Spring代碼IDEA
點(diǎn)贊
收藏

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