1. 程式人生 > 實用技巧 >node學習2

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