meilisearch 替換 elasticsearch 搜索

全文搜索用elasticsearch太佔資源了,而且速度慢。換換換換換換換。(退錢~~~~)

安裝 meilisearch

# https://github.com/meilisearch/MeiliSearch/releases

wget https://github.com/meilisearch/MeiliSearch/releases/download/v0.23.1/meilisearch-linux-amd64

mv meilisearch-linux-amd64 /usr/local/bin/meilisearch

mkdir /data/meilisearch_db

#運行
/usr/local/bin/meilisearch --db-path /data/meilisearch_db

#生產使用
/usr/local/bin/meilisearch --db-path /data/meilisearch_db --no-analytics=true --env production --master-key meili_password

文檔

https://docs.meilisearch.com/reference/

推薦直接用官方的sdk,curl調用的麻煩,還老寫錯了 :)

php sdk

https://github.com/meilisearch/meilisearch-php

composer require meilisearch/meilisearch-php guzzlehttp/guzzle http-interop/http-factory-guzzle:^1.0
use MeiliSearch\Client;

$client = new Client('http://127.0.0.1:7700', 'masterKey');

// 舉個例子
// 全市的醫院 
// hospitals
// 	id // 編號 
// 	name // 醫院名稱
// 	level // 醫院等級
// 	district // 所在市區
// 	address // 地址
// 	_geo // 座標


// 如果存在則刪除documents
$client->deleteIndexIfExists('hospitals');

// 創建documents
// primaryKey 指定主鍵 (我測試時 不指定主鍵 文檔裏如果有多個整數字段 會使用最後一個整數字段)
$client->createIndex('hospitals', ['primaryKey' => 'id']);

$index = $client->index('hospitals');

// 可過濾 (類似sql的 where)
$index->updateFilterableAttributes([
  'level',
  'district',
]);

// 可排序 ( 'id:desc', '_geoPoint(31.960546780595564, 118.88298329046941):asc')
$index->updateSortableAttributes([
  'id',
  '_geo',
]);

// 可全文搜索的字段 (不設置 默認所有字段都可以全文搜索)
$index->updateSearchableAttributes([
  'name',
]);


// 添加或者替換文檔
$documents = [
  ['id' => 1, 'name' => "南京鼓樓醫院", 'level' => '三甲', 'district' => '鼓樓區', 'address' => '江蘇省南京市鼓樓區中山路348號',  '_geo' => ['lat' => 32.060869, 'lng' => 118.789666]], 
  ['id' => 2, 'name' => "南京市江寧醫院(湖山路院區)", 'level' => '三甲', 'district' => '江寧區', 'address' => '南京市江寧區湖山路169號',  '_geo' => ['lat' => 31.961168, 'lng' => 118.876076]], 
];

$index->addDocuments($documents);



// 查詢例子

// 搜索醫院名
$query = '醫院';
$options = []; 
$index->search($query, $options)->getHits();

// 過濾出江寧區的醫院,且等級是三甲的
$options = [
	'filter' => [ "district = '江寧區'", "level = '三甲'"],
];

// 按指定座標排序
$options = [
	'sort' => [
		"_geoPoint(31.960546780595564, 118.88298329046941):asc",
	],
];

// 只返回指定字段, 默認返回所有字段
$options = [
	'attributesToRetrieve' =>  ['id', 'name'],
];

// 搜索關鍵詞 高顯返回 如 搜索 "醫院" 返回的 ['_formatted']['name'] "南京鼓樓<em>醫院</em>“
$options = [
	'attributesToHighlight' =>  ['name'],
];

// 搜索關鍵詞 返回精確的字符串索引 如 搜索 "醫院" 返回的 ['_matchesInfo']['name'] ['start' => 11, 'lenght' => 6]
$options = [
	'matches' =>  true,
];

// 可以根據'_matchesInfo' 分割成數組 ([0, string] [1, string] 1代表當前是關鍵詞)
function _split_by_matchesInfo($str, $matches) {
	$arr = [];
	$last = 0;
	$len = strlen($str);
	foreach($matches as $index => $range) {

		if ($last < $range['start']) {
			$arr[] = [0, substr($str, $last, ($range['start'] - $last))];
		}
		$arr[] = [1, substr($str, $range['start'], $range['length'])];

		$last = $range['start'] + $range['length'];
	}

	if($last < ($len - 1)) {
		$arr[] = [0, substr($str, $last)];
	}
	return $arr;
}

// 統計可過濾字段的數量 (類似 elastic 查詢的 aggs)
// 需要注意的是 facetsDistribution 字段 一定是可過濾的(updateFilterableAttributes)
$options = [
	'facetsDistribution' =>  ['district'],
];
$result = $index->search('', $options);
$facets = $result->getFacetsDistribution();
// 返回
$facets['district'] = [
  '江寧區' => 1,
  '鼓樓區' => 1,
]

對於簡單的過濾統計 基本上可以替換掉es

相同的數據 佔用內存比較下哈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章