node學習2
目錄
1.操作資料庫
本章開發一個命令列工具,用於與Elasticsearch進行互動。Elasticsearch是一個模式自由、支援RESTful的NoSQL資料庫,它通過HTTP儲存和索引JSON文件。我們的程式可以通過多種選項進行配置,並且支援高階查詢功能。它還能批量插入匯入文件。這是一個機遇JSON的文件資料庫Elasticsearch。除了操縱JSON,還會使用一個jq的命令列工具。
1.1 Elasticsearch入門
Elasticsearch是一個分散式、面向文件的NoSQL資料庫,提供豐富的查詢功能,包括全文搜尋、詞幹搜尋、模式搜尋。Elasticsearch還可以執行各種聚合查詢,使用過濾器,執行數字比較。
當然,沒有一種工具是萬能的,Elasticsearch也不例外。但考慮到古藤堡專案的檔案特性(包括書籍名稱,作者),Elasticsearch很適合儲存這些資料。我們需要先把文件儲存在Elasticsearch,後面在這個基礎上開發RESTful API。
Elasticsearch的叢集架構提供了非常好的可擴充套件性和可靠性。它的分片和複製機制不但可以防止停機,還能實現並行查詢。與Elasticsearch進行互動必須依靠正確的HTTP請求,後面會介紹
1.1.1 安裝先決條件
Elasticsearch是使用java8開發的,所以要安裝java 執行時環境。建議安裝java8。在命令列執行java-version,確認java已安裝。
java -version
1.1.2 安裝Elasticsearch
去Elasticsearch的官網上下https://www.elastic.co/cn/downloads/elasticsearch
下載後將其解壓,在命令列執行
bin\elasticsearch
輸出內容如下
1.2 使用Commader建立命令列程式
生成一個命令列程式的框架,該命令列程式能訪問Elasticsearch的某些功能。開始前,建立一個package.json檔案。建立目錄esclu,作為Elasticsearch互動的專案目錄。
進入esclu目錄,執行npm init
,
1.2.1 介紹Commader和Request模組
使用一個名為Commader的模組,它可以在Node.js中構建複雜的命令列工具。
儘管Node.js的內建HTTP模組對HTTP請求提供了基本支援,但其功能還不夠強大。下面將使用更高階的Request模組簡化HTTP請求和處理非同步響應的工作。
Commader和Request模組可以減少程式碼,同時提供豐富的功能。安裝這2個模組
npm install --save --save-exact [email protected] [email protected]
Commader模組不是npm中唯一一個可以幫助建立命令列程式的模組。例如yargs模組就具有許多與Commander相同的功能。使用yargs,你不必事先明確宣告每個選項,只要在開發時所需選項和資料型別做檢查。
Request模組也不是唯一一個可以簡化HTTP請求的模組。另一個類似的模組是superagent,但其目標主要是相容瀏覽器和Node.js。
還有一個與Request類似的模組是node-fetch,它支援Fetch API,Fetch API是用於取代XMLHttpRequest的新API,後面將使用它。
1.2.2 使用Commander建立基本的命令列程式
Commander模組可以處理各種細節:強制檢查所需的引數,解析命令列選項,解析標誌的縮寫即別名等。
首先,需要一個名為esclu(無副檔名)的可執行檔案,這樣可以直接執行它。而不必顯式地執行Node.js。將#!放在Node.js檔案的第一行行首,它告訴unix這是一個可執行檔案。我們將再次使用它,不同的是,這次將工作的javascript拆分到不同的獨立檔案總。首先建立一個名為esclu的檔案,然後
檔案內容如下
#! /usr/bin/env node
require('./index.js');
儲存esclu檔案,使用chmod命令賦予執行許可權。
chmod +x esclu
在esclu目錄下新建firstCommander.js 檔案,檔案如下:
#! /usr/bin/env node
const program = require('commander');
const request = require('request');
console.log(program)
program
.allowUnknownOption()
.version('0.0.1')
.usage('translator <cmd> [input]')
const url = `http://fanyi.youdao.com/openapi.do?keyfrom=toaijf&key=868480929&type=data&doctype=json&version=1.1`;
const fullUrl = (path = '') => {
program.host = 'localhost';
program.port = '9200';
program.index = 'books';
let url = `http://${program.host}:${program.port}`;
if (program.index) {
console.log('program index is' + program.index);
url += program.index + "/";
if (program.type) {
url += program.type + '/';
}
}
console.log('program index is' + program.index);
return url + path.replace(/^\/*/, '');
}
program
.command('url [path]')
.description('generate the URL for the options and path (default is /)')
.action((path = '/') => console.log(fullUrl(path)));
// program
// .command('get [path]')
// .description('perform an HTTP GET request for path (default is /')
// .action((path = '/') => {
// const options = {
// url: fullUrl(path),
// json: program.json
// }
// request(options, (err, res, body) => {
// if (program.json) {
// console.log(JSON.stringify(err || body))
// } else {
// if (err) throw err;
// console.log(body);
// }
// });
// });
program
.command('create-index')
.description('crete an index')
.action((index) => {
console.log('ddd')
// if (!program.index) {
// const msg = 'No index specified! Use --index <name>';
// if (!program.json) throw Error(msg);
// console.log(JSON.stringify({ error: msg }));
// return;
// }
// console.log('crete-index');
request.put(fullUrl(), handleResponse);
})
const handleResponse = (err, res, body) => {
if (program.json) {
console.log(JSON.stringify(err || body));
} else {
if (err) throw err;
console.log(body);
}
}
program
.command('query')
.description('翻譯輸入')
.action((obj) => {
console.log('ee')
});
program.parse(process.argv);
if (!process.argv[2]) {
program.help();
console.log();
}
注意在檔案的頂部,我們將package.json賦值給一個名為pkg的常量。Node.js的require()方法可以讀取JSON檔案以及使用Javascript編寫的模組。
接下來設定Commander提供的program物件。在設定版本、描述和用法字串後,我們列舉了一些標誌及其預設值。運用哪些選項取決於具體的需求,稍後會利用這些選項和Elasticsearch進行互動。
除此之外,我們通過呼叫program.parse來解析Node.js命令列選項。
最後,檢查program物件的args陣列是否包含除字串以外的物件。除非使用者提供的引數命中了一個命名過的命令,不然Commander會把引數作為字串儲存到program.args中。稍後我們會定義一些命令。這段程式碼可以確保如果使用者輸入我們無法識別的引數,他們也會看到和輸入-h一樣的結果。
儲存這段程式碼,在esclu專案目錄開啟終端,執行下面指令碼:
$ ./esclu
Usage: esclu [options] <command> [...]
Options:
-h, --help output usage information
-V, --version output the version number
-o --host <hostname> hostname [localhost]
-p --port <number> port number [9200]
-j --json format output as JSON
-i --index <name> which index to use
-t --type <type> default type for bulk operations
正如上面看到的,幫助已經工作了。還可以嘗試version選項,確認是否和package.json中指定的值相同。
1.2.3 給你的程式新增命令
接下來要給esclu新增命令以便於Elasticsearch互動。由於Elasticsearch是個RESTful資料庫,所以,與它進行互動首先要編寫正確的URL。
REST是representational state transfer(表現層狀態轉換)的縮寫。RESTful的API都是基於HTTP的,其資源只能通過URL來獲取。請求資源和更改資源必須用特定HTTP方法發出HTTP請求。比如,HTTP GET方法用於檢索資源,HTTP PUT用於傳送要儲存的資源。
在Elasticsearch中,RESTful資源屬於JSON文件。每個文件都存放在一個索引中,並且設定了相應的型別。要為Elasticsearch文件構建一個URL,首先需要拼接你感興趣的索引,然後拼接你感興趣的物件型別。(使用斜槓分割)。要獲取有關整個叢集的資訊,可以向根目錄發出HTTP GET請求。
建立一個索引來儲存建立的圖書資料,要獲取名為books的索引資訊,請使用GET請求:
http://localhost:9200/books API
URL需要包含索引和型別資訊,為此,請將fullUrl()方法新增到esclu程式中,放在require行之前。
可以用這種方式執行命令
node .\firstCommander.js create-index