教程[10] MeiliSearch 初体验

开篇废话

之前有好几个项目因为偷懒用的 JSON 数据库又变成 0 字节灰飞烟灭了数了数炸了七八回了,想着还是找个阳间的东西存储数据 ,然后又看到妮可草经常安利 MeiliSearch (就感觉到快),于是就打算玩玩这玩意了

其实可以存 mongodb 之类的,这里作纯探索别的玩法
这样不用专门对搜索进行优化了,好麻烦,虽然最后结果是失败的(如果使用 %Like% 搜索,相当于每次搜索把数据库的表 grep 了一回,所以在这里我才想用 MeiliSearch

前排提醒,各版本已索引数据是不通用的,请及时备份。
更新篇传送门 https://blog.huggy.moe/posts/2022/4-meilisearch-2/

安装 & 配置

Arch Linux 倒是没什么好说的

pacman -S MeiliSearch

其它系统配置下源,或者直接下 bin 也行

参考 官方教程
然后编辑配置文件

nano /etc/MeiliSearch.conf

配置文件十分地简洁,改下绑定端口还有 masterkey 就好

# MeiliSearch configuration
#MEILI_ENV=
MEILI_HTTP_ADDR=192.168.233.2:7700
MEILI_MASTER_KEY=key@123
MEILI_NO_ANALYTICS=no

这里的 MEILI_HTTP_ADDR 就是监听端口,如果只在本地运行,那么根本不需要改,不填写默认是 127.0.0.1:7700

MEILI_MASTER_KEY 乱敲键盘就好(别碰特殊字符大概还好)

然后运行 && 开机启动

systemctl enable MeiliSearch --now

不出意外应该就成功运行了。

netstat -tunlp | grep MeiliSearch
# tcp        0      0 192.168.191.11:4000     0.0.0.0:*               LISTEN      602200/MeiliSearch

使用

这里参照 官方教程
还有就是使用了 postman 请求 MeiliSearch 的工具 (官方的 curl 例子其实也很详细了,直接复制用改改也行)
用法其实和一些 noSql 数据库有点像,就是一种拿来存 json 数据的轮子啦,主要是

然而这个快 是建立在有分词的情况了,后面会说到这种分词的牺牲方面

鉴权

参考官方文档

一开始肯定要聊一下鉴权方面了,图省事的话,甚至可以不鉴权(别开放公网访问大概就行?)
有个 masterkey 懒一点话直接在 header 填上 masterkey 也行
也可以用 masterkey 生成 public key / private key 来使用
这里也顺便介绍下请求 melisearch 最基本的使用。

官方例子已经很明白了:

curl \
-H "X-Meili-API-Key: 123" \
-X GET 'http://localhost:7700/keys'

这里会返回 public key / private key :

{
    "private": "8c222193c4dff5a19689d637416820bc623375f2ad4c31a2e3a76e8f4c70440d",
    "public": "948413b6667024a0704c2023916c21eaf0a13485a586c43e4d2df520852a4fb8"
}

这里对 private / public 不是 RSA 那种非对称加密用到的,所以不用想到这方面,简单地来说 public key 大概是可以进行只读操作(也就是说我可以直接暴露 melisearch api 到前端)
而 private key 是可以对数据甚至表进行操作,约等于 master key
更多细节可以参考官方对鉴权的说明

然而这玩意在更改了 masterkey 后才会变 好随意(((

创建 index

官方文档
这里 MeiliSearch 的 index 相当于数据库的一个表名,然后这个表必须有个独特的字段(一般来说就是 id 啦)

curl \
-X POST 'http://localhost:7700/indexes' \
--data '{
    "uid": "test",
    "primaryKey": "id"
}'

这里的 uid 就是表名,然后 primaryKey 就是数据库索引的名字(比如说 id)。
然后 status code 提示 201 created 就表示创建成功了~

插入数据

官方文档
melisearch 插入数据就类似 nosql 数据库(比如 mongodb)

curl \
-X POST 'http://localhost:7700/indexes/test/documents' \
--data '[{
    "id": 1,
    "title": "test",
    "author": "huggy"
}]'

注意 这里插入数据都是要包含在一个 array 内的,哪怕是只有一行数据也要用 [] 包住才行。

这就是最基本的插入数据请求了

其它家基本都是 insert 就这边是 adddocuments (sdk 里面是这样的名字)

查询数据

官方文档

查询数据才是 melisearch 的厉害之处,就感觉到快

curl \
-X POST 'http://localhost:7700/indexes/test/search' \
--data '{ "q": "huggy", "offset":0,"limit":100 }'

这里的 q = query 就是要查询的文字
然后 filter 大概可以做更精确的
其它的还是看官方文档快点(
返回数据大概这样:

search

自由发挥

这里大概介绍完了基本用法,似乎还少了点,比如排序之类的?
很抱歉,meliseatch 对于排序之类的是弱化了的,不能在搜索的时候插入排序的规则。

截止 melisearch 0.20.0 好像还是这样

也就是可以全局排序,但是不能在搜索的时候附加排序规则进去(不像 mysql order by 就好了)

在 melisearch 有个 ranking rules 可以全局排序

value 垃圾说明
typo 按照错别字数量增加而排序 (没看懂 qaq)
words 按照关键词匹配量而排序
Proximity 按照关键词之间距离而排序
Attribute 根据属性排名进行排序
wordsPosition 根据关键词在文中的位置排序
exactness 根据准确/相似性排序
asc(id) 根据字段升序排列
desc(id) 根据字段降序排列

简单的说明,建议直接看官方文档好点,塑料英语太烂了

这里我做了,按照 id 来降序排序
ranking rules

请注意,更改排序方式也不是实时生效的,在 0.24.0+ 以后有个 task api 可以看索引进度。

@zaobao_bot 截止 2021 年 6 月 28 日 就是使用 MeiliSearch 来存储数据的

坑点

说了这么多,好像 MeiliSearch 作为一个 nosql 好像非常好?
实际上不是的,他缺少了很多数据库该有的功能,正如名字一样,是用来搜索为主的。
弱化的排序功能,还有中文分词功能,直接导致了无法在正常中文(不能用空格分词的语言全部中招)项目里面使用(虽然官方已经用 jieba-rs 来分词了,但还是不合人意)

举个例子(新闻版权归早报所有)

s1
s2
s3

当我搜索 合肥 关键词的时候,MeiliSearch 不知道为什么只匹配到了 ,而 是搜索无结果的。

这里我试了很多 ranking 参数,没啥解决办法。

参考官方文档
中文是依照 jieba 来生成的,如果 jieba 无法正确分词(比如合肥太短了 jieba 会认为是两个词 合 肥)那么搜索出来的结果就可能不是自己想要的了,这个问题至少在现在,因为 melisearch 的特性是无法解决的,直接用 mongodb 或者 redis 比较好点 大概。