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 commander@2.9.0 request@2.79.0

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
posted @ 2020-07-18 17:25  melimeli  阅读(134)  评论(0编辑  收藏  举报