實戰:Nodejs+Mongodb+Elasticsearch 實現簡單的搜尋
在網站建立初期,我們提供的搜尋服務很多都是基於資料庫的模糊搜尋,在效能和可用性上多少會有所缺失,所以在網站發展壯大後,就不得不增強搜尋功能。elasticsearch 的基本功能就已經足夠一般的搜尋需求。本文將介紹,如何使用 nodejs + mongodb + es 實現一個簡單而強大的全文搜尋功能,以提高網站搜尋體驗。
基本架構圖
-
資料儲存在 mongodb
-
使用 elasticsearch 作為搜尋資料庫
-
nodejs 用官方客戶端 elasticsearch-js 請求 elasticsearch
-
使用 mongo-connector 同步 mongodb 的資料到 elasticsearch
-
前端隨便請求一下
elasticsearch
本文使用的是 elasticsearch-rtf,這個庫使用的是 elasticsearch 5.1 版本,並且預裝了一些常用外掛,比如常用分詞器。
在安裝完 java 環境後,就可以直接執行 elasticsearch 目錄裡的 bin/elasticsearh。不過在虛擬機器中,會有各種像記憶體不足,檔案描述符限制等問題。所以在虛擬機器中,我們需要修改一些配置:
-
修改 config/jvm.options 裡的 jvm 記憶體為 512m
# Xms represents the initial size of total heap space # Xmx represents the maximum size of total heap space #-Xms2g #-Xmx2g -Xms512m -Xmx512m
-
修改檔案描述符上限,需要 root 許可權,然後執行
ulimit -n 65536
-
為了讓別的機器能連上 elasitcsearch 機器,需要把 config/elasticsearch.yml 裡的 network.host 修改為 0.0.0.0。另外,還需要執行如下命令
sysctl -w vm.max_map_count=262144
不然會報 vm.max_map_count 不足的錯誤。
mongodb
安裝就好,沒有坑
mongo-connector
mongo-connector 是一個 python 編寫的,用來複制 mongodb 中資料到各種搜尋資料庫的工具,支援 elasticsearch。
使用這個庫前,要先在 mongodb 中設定 replSet,具體可以檢視這裡。
另外,在執行中需要用到 elastic_doc_manager 這個庫,需要另外安裝,在他的 README 裡沒有明確指明需要另外安裝,具體可以檢視這裡。
最後,執行:
mongo-connector -m localhost:27017 -t localhost:9200 -d elastic_doc_manager
mongo-connector 會把 mongodb 裡的資料同步到 elasticsearch。
測試資料
測試資料使用 Faker-zh-cn.js 生成。這個庫是 faker.js 的中文版。程式碼如下:
const { MongoClient } = require('mongodb')
const faker = require('faker-zh-cn')
const DB_URL = 'mongodb://192.168.134.125:27017/test'
faker.locale = 'zh_CN'
const insertData = function(db, callback) {
let collection = db.collection('data')
let data = []
for (let i = 0; i <= 1000; i++) {
data.push({
"name": faker.Name.findName(),
"address": `${faker.Address.city()},${faker.Address.streetName()},${faker.Address.streetAddress()}`,
"description": faker.Lorem.paragraph()
})
}
collection.insert(data, function(err, result) {
if(err) {
console.log('Error:'+ err)
return
}
console.log('success')
callback && callback(result)
})
}
MongoClient.connect(DB_URL, function (err, db) {
if (err) {
return console.log(err)
}
console.log('連線成功')
insertData(db)
})
替換分詞器
生成測試資料後,使用 elasticsearch 的 rest api 測試搜尋,發現搜尋結果並不理想。比如使用查詢條件 q=王者農藥,出來的結果除了王者、農藥相關的結果,連包含王、者、農或藥的結果都出來了,說明搜尋預設對中文以字為單位分詞,我們需要替換分詞器。
elasticsearch-analysis-ik 是一個流行的中文分詞庫,在 elasticsearch-rtf 中已經整合,可直接使用。
更換分詞器需要對 elasticsearch 的對映重定義。使用 elasticsearch 的 rest api 進行設定,會報錯,大概意思就是已經存在資料的索引的對映不能被修改,所以要另闢蹊徑。
後來查到,只需要根據舊的索引和型別,重新建立一個索引,然後把想要修改的索引,reindex 到新索引即可。新索引的對映帶上了 analyzer: "ik_smart" 的宣告,就可以用上這個分詞器了。
最後,搜尋結果變得正常了一點,只會出現王者和農藥相關的結果了,說明分詞器起效了。
nodejs 程式碼
用的 express 隨便意思一下
const { Client } = require('elasticsearch')
const INDEX = 'index'
const express = require('express')
const app = express()
let client = new Client({
host: '192.168.134.125:9200',
log: 'trace'
})
app.use(express.static(__dirname + '/public'))
app.get('/', (req, res) => {
res.send('Hello World')
})
app.get('/search/:keyword?', (req, res) => {
client.search({
q: req.params.keyword,
index: INDEX,
size: 999
}).then(function (body) {
var hits = body.hits.hits
res.send(hits)
}, function (error) {
console.trace(error.message)
})
})
console.log('listening port: 3000')
app.listen(3000)
結果
前端就是一個簡單的頁面,呼叫 nodejs 的介面,看起來是這樣的
最後
本人才疏學淺,如有紕漏,還望指正。
參考 :
https://segmentfault.com/a/1190000003773614
相關文章
- Elasticsearch 實現簡單搜尋Elasticsearch
- Elasticsearch搜尋功能的實現(五)-- 實戰Elasticsearch
- Meteor+MongoDB 實現簡單的即時搜尋MongoDB
- Android開源實戰:手把手教你實現一個簡單 & 好用的搜尋框(含歷史搜尋記錄)Android
- SimpleAISearch:C# + DuckDuckGo 實現簡單的AI搜尋AIC#Go
- Redis 實戰 —— 10. 實現內容搜尋、定向廣告和職位搜尋Redis
- 微信小程式 簡易搜尋功能實現微信小程式
- 使用 JavaScript 實現簡單候選項推薦功能(模糊搜尋)JavaScript
- 《ElasticSearch6.x實戰教程》之簡單搜尋、Java客戶端(上)ElasticsearchJava客戶端
- 搜尋引擎:MapReduce實戰----倒排索引索引
- ASP智慧搜尋的實現 (轉)
- Laravel + Elasticsearch 實現中文搜尋LaravelElasticsearch
- Jquery + Bootstrap 實現搜尋框jQueryboot
- PHP實現搜尋附近的人PHP
- 實現延遲搜尋功能
- ElasticSearch 簡單的 搜尋 聚合 分析Elasticsearch
- 基於 Elasticsearch 的站內搜尋引擎實戰Elasticsearch
- 基於 Mysql 實現一個簡易版搜尋引擎MySql
- 如何用Redis實現搜尋介面Redis
- laravel8實現ES搜尋Laravel
- elasticsearch實現基於拼音搜尋Elasticsearch
- Elasticsearch學習系列三(搜尋案例實戰)Elasticsearch
- 原生javascript實現的選取搜尋元件JavaScript元件
- 海量資料搜尋---demo展示百度、谷歌搜尋引擎的實現谷歌
- vue2實現搜尋結果中的搜尋關鍵字高亮Vue
- Sunday搜尋演算法實現演算法
- BM搜尋演算法C實現演算法
- javascript實現二叉搜尋樹JavaScript
- Python如何實現窮舉搜尋?Python
- 基於Elasticsearch實現搜尋建議Elasticsearch
- CSS 實現搜尋相關互動CSS
- 使用 Laravel Scout + ElasticSearch 實現全文搜尋LaravelElasticsearch
- ELKStack及Solr企業級搜尋引擎實戰Solr
- YII框架中自帶的表單,搜尋,分頁程式碼的實現框架
- PHP - 實現類似於百度的實時搜尋PHP
- 二叉搜尋樹的python實現Python
- 二分搜尋演算法的實現演算法
- 【Django】組合條件的搜尋功能實現Django