使用meilisearch实现多属性搜索功能

黄鹏宇 104 2023-10-06

一、需求

  1. 图片有很多属性,放在不同的数据表里。可以根据不同属性,筛选出图片【图1】
  2. 不光要能命中图片,还需要返回每次筛选后,剩余的属性及数量【图2】
  3. 速度要快

image-1696583514689

image-1696583474510

最终效果

image-1696584835111
即接口为:

  • url: /picture/list/search
  • payload:
{
    "keyword":"淬火",
    "pageIndex":1,
    "pageSize":999,
    "sortValue":"createTime",
    "picTypeValue":"all",
    "materialTypeValues":[],
    "brandValues":[],
    "statusValues":[],
    "heatStatusValues":[
        "淬火",
        "回火"
    ],
    "orgValues":[
        "粒状贝氏体"
    ],
    "corValues":[],
    "corReagentValues":[],
    "authorUnitValues":[],
    "authorValues":[],
    "picColumnValues":[]
}
  • return
{    "processingTimeMs":0,
    "hitsPerPage":999,
    "totalHits":1,
    "query":"淬火",
    "totalPages":1,
    "page":1,
    "hits":[
        {
            "picBrand":{
                "count":0,
                "id":17,
                "desc":"耐候钢"
            },
            "subject":"耐候钢-淬火-粒状贝氏体",
            "materialType":{
                "count":0,
                "id":1,
                "desc":"钢"
            },
            "typeName":"彩色金相",
            "columnList":[],
            "orgList":[
                {
                    "count":0,
                    "id":22,
                    "desc":"粒状贝氏体"
                }
            ],
            "likeCount":2,
            "userId":33,
            "corDesc":"",
            "heatStatusList":[
                {
                    "count":0,
                    "id":6,
                    "desc":"淬火"
                }
            ],
            "createTime":1688089162000,
            "heatDesc":"",
            "likeStatus":0,
            "id":2,
            "passed":1,
            "viewCount":66,
            "orgDesc":""
        }
    ],
    "facetDistribution":{
        "corType.desc":{},
        "author.name":{
            "fengyijie":1
        },
        "picBrand.desc":{
            "耐候钢":1
        },
        "subject":{
            "耐候钢-淬火-粒状贝氏体":1
        },
        "columnList.desc":{},
        "typeName":{
            "彩色金相":1
        },
        "authorUnit.desc":{},
        "microList.desc":{ },
        "orgList.desc":{
            "粒状贝氏体":1
        },
        "materialType.desc":{
            "钢":1
        },
        "statusList.desc":{},
        "compositionList.name":{},
        "heatStatusList.desc":{
            "淬火":1
        },
        "corReagent.desc":{

        }
    },
    "facetStats":{

    }
}

二、之前的做法

由于我现有的图库数量不多(18张),所以想的是把所有图片数据都放至缓存中,然后编码来实现。
但是写的代码,又长又不好维护,并且如果添加新属性,还得改代码。
image-1696583459972

三、现在的做法

使用meiliSearch,一个轻量化的搜索引擎,类似于es

大致步骤如下

1. 中间件相关

  • 安装
    • 使用docker安装
    • 导入备份(dump)
  • 配置
    • 配置KEY
  • 配置index
    • 创建index
    • 配置可排序项目(sortable-attributes)
    • 配置可搜索项目(filterable-attributes)
    • 修改faceting的排序方式 (sortFacetValuesBy)

2. 封装java方法

  • 通过api对document进行增删改
  • 根据前端的搜索参数,转化为搜索引擎所需的参数

3. 前端