安装

Github安装链接

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

Gitee安装链接(含设定淘宝镜像源,适用中国大陆)

curl -o- https://gitee.com/RubyMetric/nvm-cn/raw/main/install.sh | bash

更新nvm

安装时可能使用旧版的nvm程序,可在安装后执行一次更新命令。

nvm update
上述命令执行时,请确保有权限。

例外操作

可能会遭遇受限权限写入或者需要重载环境等情况,通常执行以下命令可恢复正常。

# 更新权限
chmod +x ~/.nvm/nvm.sh
# 重新加载环境变量
source ~/.bashrc

nvm指令

  1. 查看当前机器安装版本

    nvm ls
  2. 查看可以云端版本

    nvm ls-remote
  3. 安装指定版本Node.js

    nvm install [<version>]
  4. 卸载指定Node.js版本

    nvm uninstall [<version>]
  5. 使用指定Node.js版本

    nvm use [<version>]
  6. 当前使用Node.js版本

    nvm current
  7. 在对应项目中切换不同Node.js版本

在项目中创建项目所需要的版本声明

touch .nvmrc
echo "v18.19.0" >> .nvmrc

在指定目录下使用nvm use即可切换到对应版本

也可以使用其他方式在使用npm时自动辨识项目的版本文件进行切换操作。

NVM命令输出选项

原文

Node Version Manager (v0.39.5)

Note: <version> refers to any version-like string nvm understands. This includes:
  - full or partial version numbers, starting with an optional "v" (0.10, v0.1.2, v1)
  - default (built-in) aliases: node, stable, unstable, iojs, system
  - custom aliases you define with `nvm alias foo`

 Any options that produce colorized output should respect the `--no-colors` option.

Usage:
  nvm --help                                  Show this message
    --no-colors                               Suppress colored output
  nvm --version                               Print out the installed version of nvm
  nvm install [<version>]                     Download and install a <version>. Uses .nvmrc if available and version is omitted.
   The following optional arguments, if provided, must appear directly after `nvm install`:
    -s                                        Skip binary download, install from source only.
    -b                                        Skip source download, install from binary only.
    --reinstall-packages-from=<version>       When installing, reinstall packages installed in <node|iojs|node version number>
    --lts                                     When installing, only select from LTS (long-term support) versions
    --lts=<LTS name>                          When installing, only select from versions for a specific LTS line
    --skip-default-packages                   When installing, skip the default-packages file if it exists
    --latest-npm                              After installing, attempt to upgrade to the latest working npm on the given node version
    --no-progress                             Disable the progress bar on any downloads
    --alias=<name>                            After installing, set the alias specified to the version specified. (same as: nvm alias <name> <version>)
    --default                                 After installing, set default alias to the version specified. (same as: nvm alias default <version>)
  nvm uninstall <version>                     Uninstall a version
  nvm uninstall --lts                         Uninstall using automatic LTS (long-term support) alias `lts/*`, if available.
  nvm uninstall --lts=<LTS name>              Uninstall using automatic alias for provided LTS line, if available.
  nvm use [<version>]                         Modify PATH to use <version>. Uses .nvmrc if available and version is omitted.
   The following optional arguments, if provided, must appear directly after `nvm use`:
    --silent                                  Silences stdout/stderr output
    --lts                                     Uses automatic LTS (long-term support) alias `lts/*`, if available.
    --lts=<LTS name>                          Uses automatic alias for provided LTS line, if available.
  nvm exec [<version>] [<command>]            Run <command> on <version>. Uses .nvmrc if available and version is omitted.
   The following optional arguments, if provided, must appear directly after `nvm exec`:
    --silent                                  Silences stdout/stderr output
    --lts                                     Uses automatic LTS (long-term support) alias `lts/*`, if available.
    --lts=<LTS name>                          Uses automatic alias for provided LTS line, if available.
  nvm run [<version>] [<args>]                Run `node` on <version> with <args> as arguments. Uses .nvmrc if available and version is omitted.
   The following optional arguments, if provided, must appear directly after `nvm run`:
    --silent                                  Silences stdout/stderr output
    --lts                                     Uses automatic LTS (long-term support) alias `lts/*`, if available.
    --lts=<LTS name>                          Uses automatic alias for provided LTS line, if available.
  nvm current                                 Display currently activated version of Node
  nvm ls [<version>]                          List installed versions, matching a given <version> if provided
    --no-colors                               Suppress colored output
    --no-alias                                Suppress `nvm alias` output
  nvm ls-remote [<version>]                   List remote versions available for install, matching a given <version> if provided
    --lts                                     When listing, only show LTS (long-term support) versions
    --lts=<LTS name>                          When listing, only show versions for a specific LTS line
    --no-colors                               Suppress colored output
  nvm version <version>                       Resolve the given description to a single local version
  nvm version-remote <version>                Resolve the given description to a single remote version
    --lts                                     When listing, only select from LTS (long-term support) versions
    --lts=<LTS name>                          When listing, only select from versions for a specific LTS line
  nvm deactivate                              Undo effects of `nvm` on current shell
    --silent                                  Silences stdout/stderr output
  nvm alias [<pattern>]                       Show all aliases beginning with <pattern>
    --no-colors                               Suppress colored output
  nvm alias <name> <version>                  Set an alias named <name> pointing to <version>
  nvm unalias <name>                          Deletes the alias named <name>
  nvm install-latest-npm                      Attempt to upgrade to the latest working `npm` on the current node version
  nvm reinstall-packages <version>            Reinstall global `npm` packages contained in <version> to current version
  nvm unload                                  Unload `nvm` from shell
  nvm which [current | <version>]             Display path to installed node version. Uses .nvmrc if available and version is omitted.
    --silent                                  Silences stdout/stderr output when a version is omitted
  nvm cache dir                               Display path to the cache directory for nvm
  nvm cache clear                             Empty cache directory for nvm
  nvm set-colors [<color codes>]              Set five text colors using format "yMeBg". Available when supported.
                                               Initial colors are:
                                                  bygre
                                               Color codes:
                                                r/R = red / bold red
                                                g/G = green / bold green
                                                b/B = blue / bold blue
                                                c/C = cyan / bold cyan
                                                m/M = magenta / bold magenta
                                                y/Y = yellow / bold yellow
                                                k/K = black / bold black
                                                e/W = light grey / white
Example:
  nvm install 8.0.0                     Install a specific version number
  nvm use 8.0                           Use the latest available 8.0.x release
  nvm run 6.10.3 app.js                 Run app.js using node 6.10.3
  nvm exec 4.8.3 node app.js            Run `node app.js` with the PATH pointing to node 4.8.3
  nvm alias default 8.1.0               Set default node version on a shell
  nvm alias default node                Always default to the latest available node version on a shell

  nvm install node                      Install the latest available version
  nvm use node                          Use the latest version
  nvm install --lts                     Install the latest LTS version
  nvm use --lts                         Use the latest LTS version

  nvm set-colors cgYmW                  Set text colors to cyan, green, bold yellow, magenta, and white

Note:
  to remove, delete, or uninstall nvm - just remove the `$NVM_DIR` folder (usually `~/.nvm`)

译文

个人翻译仅供参考,请以自己实际理解为准。

Node 版本管理器 (v0.39.5)

注意:<version> 指的是 nvm 能理解的任何类似版本的字符串。这包括:
  - 完整或部分版本号,以可选的 "v" 开头(0.10, v0.1.2, v1)
  - 内置的默认别名:node, stable, unstable, iojs, system
  - 你通过 `nvm alias foo` 定义的自定义别名

任何产生彩色输出的选项都应该尊重 `--no-colors` 选项。

用法:
  nvm --help                                  显示此消息
    --no-colors                               抑制彩色输出
  nvm --version                               打印已安装的 nvm 版本
  nvm install [<version>]                     下载并安装一个 <version>。如果省略版本号,则使用 .nvmrc(如果可用)。
   如果提供了以下可选参数,则必须直接出现在 `nvm install` 后:
    -s                                        跳过二进制下载,只从源码安装。
    -b                                        跳过源码下载,只从二进制安装。
    --reinstall-packages-from=<version>       安装时,重新安装在 <node|iojs|node 版本号> 中安装的包
    --lts                                     安装时,只选择长期支持(LTS)版本
    --lts=<LTS 名称>                          安装时,只选择特定 LTS 系列的版本
    --skip-default-packages                   安装时,如果存在默认包文件,则跳过
    --latest-npm                              安装后,尝试升级到给定 node 版本上最新可用的 npm
    --no-progress                             禁用任何下载的进度条
    --alias=<名称>                            安装后,将指定的别名设置为指定的版本。 (与 `nvm alias <名称> <版本>` 相同)
    --default                                 安装后,将默认别名设置为指定的版本。 (与 `nvm alias default <版本>` 相同)
  nvm uninstall <version>                     卸载一个版本
  nvm uninstall --lts                         使用 `lts/*` 的自动 LTS(长期支持)别名进行卸载(如果可用)。
  nvm uninstall --lts=<LTS 名称>              使用提供的 LTS 系列的自动别名进行卸载(如果可用)。
  nvm use [<version>]                         修改 PATH 以使用 <version>。如果省略版本号,则使用 .nvmrc(如果可用)。
   如果提供了以下可选参数,则必须直接出现在 `nvm use` 后:
    --silent                                  静默 stdout/stderr 输出
    --lts                                     使用 `lts/*` 的自动 LTS(长期支持)别名(如果可用)。
    --lts=<LTS 名称>                          使用提供的 LTS 系列的自动别名(如果可用)。
  nvm exec [<version>] [<command>]            在 <version> 上运行 <command>。如果省略版本号,则使用 .nvmrc(如果可用)。
   如果提供了以下可选参数,则必须直接出现在 `nvm exec` 后:
    --silent                                  静默 stdout/stderr 输出
    --lts                                     使用 `lts/*` 的自动 LTS(长期支持)别名(如果可用)。
    --lts=<LTS 名称>                          使用提供的 LTS 系列的自动别名(如果可用)。
  nvm run [<version>] [<args>]                在 <version> 上用 <args> 作为参数运行 `node`。如果省略版本号,则使用 .nvmrc(如果可用)。
   如果提供了以下可选参数,则必须直接出现在 `nvm run` 后:
    --silent                                  静默 stdout/stderr 输出
    --lts                                     使用 `lts/*` 的自动 LTS(长期支持)别名(如果可用)。
    --lts=<LTS 名称>                          使用提供的 LTS系列的自动别名(如果可用)。
  nvm current                                 显示当前激活的 Node 版本
  nvm ls [<version>]                          列出安装的版本,如果提供了 <version> 则匹配给定版本
    --no-colors                               抑制彩色输出
    --no-alias                                抑制 `nvm alias` 输出
  nvm ls-remote [<version>]                   列出可供安装的远程版本,如果提供了 <version> 则匹配给定版本
    --lts                                     列出时,只显示长期支持(LTS)版本
    --lts=<LTS 名称>                          列出时,只显示特定 LTS 系列的版本
    --no-colors                               抑制彩色输出
  nvm version <version>                       将给定描述解析为单个本地版本
  nvm version-remote <version>                将给定描述解析为单个远程版本
    --lts                                     列出时,只从长期支持(LTS)版本中选择
    --lts=<LTS 名称>                          列出时,只从特定 LTS 系列的版本中选择
  nvm deactivate                              撤销 `nvm` 对当前 shell 的影响
    --silent                                  在版本省略时静默 stdout/stderr 输出
  nvm alias [<pattern>]                       显示以 <pattern> 开头的所有别名
    --no-colors                               抑制彩色输出
  nvm alias <name> <version>                  设置一个名为 <name> 的别名,指向 <version>
  nvm unalias <name>                          删除名为 <name> 的别名
  nvm install-latest-npm                      尝试在当前 node 版本上升级到最新可用的 `npm`
  nvm reinstall-packages <version>            将 <version> 中包含的全局 `npm` 包重新安装到当前版本
  nvm unload                                  卸载 shell 中的 `nvm`
  nvm which [current | <version>]             显示安装的 node 版本的路径。如果省略版本号,则使用 .nvmrc(如果可用)。
    --silent                                  当版本省略时静默 stdout/stderr 输出
  nvm cache dir                               显示 nvm 缓存目录的路径
  nvm cache clear                             清空 nvm 的缓存目录
  nvm set-colors [<颜色代码>]                  使用格式 "yMeBg" 设置五种文本颜色。当支持时可用。
                                               初始颜色为:
                                                  bygre
                                               颜色代码:
                                                r/R = 红色 / 加粗红色
                                                g/G = 绿色 / 加粗绿色
                                                b/B = 蓝色 / 加粗蓝色
                                                c/C = 青色 / 加粗青色
                                                m/M = 品红色 / 加粗品红色
                                                y/Y = 黄色 / 加粗黄色
                                                k/K = 黑色 / 加粗黑色
                                                e/W = 浅灰色 / 白色
示例:
  nvm install 8.0.0                     安装特定版本号
  nvm use 8.0                           使用最新可用的 8.0.x 版本
  nvm run 6.10.3 app.js                 使用 node 6.10.3 运行 app.js
  nvm exec 4.8.3 node app.js            用指向 node 4.8.3 的 PATH 运行 `node app.js`
  nvm alias default 8.1.0               在 shell 上设置默认 node 版本
  nvm alias default node                始终默认在 shell 上使用最新可用的 node 版本

  nvm install node                      安装最新可用版本
  nvm use node                          使用最新版本
  nvm install --lts                     安装最新的 LTS 版本
  nvm use --lts                         使用最新的 LTS 版本

  nvm set-colors cgYmW                  将文本颜色设置为青色、绿色、加粗黄色、洋红色和白色

注意:
  要移除、删除或卸载 nvm - 只需删除 `$NVM_DIR` 文件夹(通常在 `~/.nvm`)

0. 准备物料

物料用途
16GB以上U盘用于引导和存放重装系统介质
微PE工具箱安装文件用于引导电脑进入工具箱安装系统
系统镜像依照您的电脑当前的系统版本准备,本文以Win10为例

1. 部署拯救U盘

非常强烈大家使用一个U盘提前部署PE系统,且部署此系统不会影响正常U盘的使用,以备系统崩溃或者紧急修复使用。

1.1 获取微PE工具箱

本文推荐微PE工具箱,推荐的点:简单,边界,无广告。

下载地址:https://www.wepe.cn/download.html

微PE工具箱下载图

如何选择版本:

  1. 一般选择最新的即可,如果最新的PE工具箱无法运行,则直接安装最老版本。
  2. 如果你了解电脑的启动方式为UEFI,则选择最新,反之最老

1.2 安装微PE工具箱

准备一个大于16GB的U盘,请备份U盘中的数据,因为在接下来的过程中会格式化U盘。

打开下载的文件,选择右下角的其他安装方式:安装到U盘

微PE安装界面

切换到安装到U盘界面,默认选项一般无需改动,但建议勾选下面两个选项,最后选择安装到U盘即可

  • [x] 包含DOS工具
  • [x] 同时复制安装包

安装到U盘界面

⚠ 在安装前再次提示:

安装会格式化U盘:指U盘的数据会被全部清空,请提前备份数据!

暂时关闭安防软件:因为需要对U盘分区以及加载引导,部分安防软件会阻止程序写入。

最后等待软件提示安装成功即可。

1.3 认识新U盘

在安装成功后,电脑上会识别出2个分区:

分区名可使用?备注
未命名
(或者根据安装时填写的U盘卷名,通常也是空间最大的一个)
可以日常使用U盘文件存放分区
EFI不可以用于引导急救系统,不要修改内部文件

在日常使用过程中建议为日常使用分区做独立标识名,以便自己或借给他人使用能够了解。

1.4 复制安装镜像

请在U盘分区的根目录下创建一个文件夹system_images,将您的安装镜像复制到这个文件夹中。

安装镜像类型可以为:

*.ios

*.wim

*.gho

建议放您常用的系统以便安装,建议使用原版镜像或可靠的安全来源镜像。

2. 启动重装之路

2.1 了解BIOS引导

本文不会解释引导逻辑,但您需要知道目前有两种引导模式,且两者一般对应不同的分区表

  1. UEFI启动 -> GPT分区表
  2. Legacy启动 -> MBR分区表

在目前主流的电脑多数使用UEFI启动,部分老旧的电脑使用Legacy启动,但我们也可以通过引导菜单来简要查看。

引导菜单快捷键:
不同品牌引导菜单快界面

如果您的电脑不在上述表中或按键无响应,则需要自行百度一下,你就知道。

2.2 选择启动设备

如果成功进入引导菜单,将会看到下面的示例引导菜单:

支持UEFI启动,一般在设备名称前会有UEFI或者EFI字样,选择含有此前缀的U盘,查看是否能够正常进入PE工具箱系统画面。

此处为WindowsPE系统选择界面:

默认等待进入第一选项或者直接回车。

如果第一个选项在您的电脑上无法显示,则需要选择第二个选项进入。

2023-08-13T07:43:31.png

等待系统加载:

最终能够展示PE系统界面,即成功一大步~

如果在UEFI模式下启动失败,则需要使用Legacy启动重新加载PE系统。

2.3 别着急,还需要再确认分区表

在一开始介绍了电脑的两种启动模式,但这不代表你你的电脑原本就是使用现有方式进入。

如果使用Legacy启动则可以不需要再确认了,因为您的电脑只有MBR分区表。

打开分区工具:

GPT分区表:

MBR:

从上方两张图也可以很直观的看出,GPT分区表是至少有3个分区起(部分GPT也有2个分区),且首个分区也有我们一开始再认识新U盘上提到的EFI分区。

因此本着不修改原有分区表的原则,进行重装系统。

重点提示:

如果您使用UEFI启动进入PE工具箱发现分区表为MBR,则需要回到选择启动设备阶段 ,选择不含有UEFI或EFI字样的U盘设备重新启动PE工具箱。

此外解释一下为什么不修改分区表,原因有很多:

  1. 可能这个电脑原生不支持UEFI启动,或为虚拟UEFI不完善。
  2. 小白可能改了分区表可能不会配置BIOS启动模式,导致无法启动系统。
  3. 转换分区表还需要额外建立引导分区或激活分区。
  4. MBR分区不支持2TB以上的硬盘。
  5. 其他原因...

如果您大胆尝试,可以修改分区表尝试是否能够使用UEFI进行启动系统,但建议在有专业人员的指导下进行修改。

3. 改写系统的命运

3.1 改写启动!

启动桌面上CGI备份还原软件:

3.2 选择镜像

打开软件后:
软件一般会自动选择系统盘,但还需要自己再确认一下,以免格式化到其他分区。
在下方选择放在system_images文件夹下的镜像。

ISO文件或者WIM文件一般内部会有多个系统镜像,会自动弹出新的窗口再选择安装需要的系统版本:

最后再下方确认安装分区以及系统版本无误点击执行:

3.3 最终确认

需要勾选以下选项:

  • [x] 格式化
  • [x] 修复引导
  • [x] 完成后重启,

等待还原完成:

在非专业人员情况下,尽量不要动电脑以及插拔U盘。
进度条有可能会多次归零,不必担心,耐心等待安装完成自动重启。

4. 新系统命运到来

4.0 重启又进PE工具箱?

如果重启后又进入的PE工具箱,则先拔出U盘即可,然后才重启电脑。

不必担心,安装的系统文件都已写入到硬盘中。

4.1 新命运归来

新系统在启动过程中会重启数次,若能看到启动服务基本上重装完成。

按照激活系统流程,和你的新系统展开新的命运之旅吧。


文中涉及软件均来自互联网,为了系统安全,示例均为原版系统,请支持正版。

前言

在很久很久以前,一位萌新程序员小明用Docker安装了Elasticsearch,之后很久很久没有在管过了,但偶然的一次对服务器检查发现ES中存在一堆的数据,小明立马意识到ES的服务被他人使用了,急忙关闭了服务并查询如何对ES进行添加鉴权。

技术点

Elasticsearch,Nginx(可选)

实战

第一种:ES启用鉴权

本次ES运行版本为7.17.2,不同的版本可能会存在配置不同,可能需要查询下当前版本的手册较佳。

elasticsearch.yml

对配置文件添加如下配置

http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

添加配置后重启服务发现再次访问ES服务则需要提示输入账户密码,点击取消会有401的错误提示.

配置密码

配置完上一步,此时服务是不可访问,,因此我们还需要在终端配置密码。

术哥@ubuntu:/usr/share/elasticsearch# elasticsearch-setup-passwords interactive
Initiating the setup of passwords for reserved users elastic,apm_system,kibana,kibana_system,logstash_system,beats_system,remote_monitoring_user.
You will be prompted to enter passwords as the process progresses.
Please confirm that you would like to continue [y/N] y

Enter password for [elastic]: 
Reenter password for [elastic]: 
Enter password for [apm_system]: 
Reenter password for [apm_system]: 
Enter password for [kibana_system]: 
Reenter password for [kibana_system]:  
Enter password for [logstash_system]: 
Reenter password for [logstash_system]: 
Enter password for [beats_system]: 
Reenter password for [beats_system]: 
Enter password for [remote_monitoring_user]: 
Reenter password for [remote_monitoring_user]: 
Changed password for user [apm_system]
Changed password for user [kibana_system]
Changed password for user [kibana]
Changed password for user [logstash_system]
Changed password for user [beats_system]
Changed password for user [remote_monitoring_user]
Changed password for user [elastic]

Change完成后就重启服务,访问ES服务,输入账号elastic和你设置的密码既可。

第二种:使用Nginx添加Basic鉴权

此方法就比较简单了,不需要得ES内进行配置,则使用Nginx进行端口转发且添加Basic鉴权,就直接上配置文件了。

如何生成鉴权文件可参考上一篇文章【小技巧】为Web再加上一把锁

配置文件

注意:此配置文件只显示需要改动点,并不能直接复制粘贴使用


steam es{
    server 127.0.0.1:9200
}

server {

    auth_basic "admin area"; # 启用鉴权
    auth_basic_user_file "/etc/nginx/http_auth/.{domain}.pass"; # 指定鉴权文件

    location / {
        http_proxy  es;
    }
}

成果

鉴权成功

[图片未上传]

鉴权失败

[图片未上传]

额外的点

Kibana鉴权

由于我们为ES添加了鉴权,因此Kibana这块也需要在配置文件上添加对应配置

[配置中心未找到KEY]

可能会遇到的问题?

ERROR: X-Pack Security is disabled by configuration.

术哥@ubuntu:/usr/share/elasticsearch# elasticsearch-setup-passwords interactive

Unexpected response code [500] from calling GET http://127.0.0.1:9200/_security/_authenticate?pretty
It doesn't look like the X-Pack security feature is enabled on this Elasticsearch node.
Please check if you have enabled X-Pack security in your elasticsearch.yml configuration file.


ERROR: X-Pack Security is disabled by configuration.

你服务压根没重启吧。

前言

有几次在学习的时候,官方提供的工具刚好是一个对Web工具没有任何加密措施,毕竟学习是无时无刻(说白了就是无时无刻的卷),虽然都是一些学习数据,将服务直接暴露在公网上总是觉得不安全,因此对Web服务额外进行Basic验证。

技术点

Nginx+htpasswd

实战

如果你的机器上安装的是Apache服务,那么htpasswd也许是会附带安装的,但如果你安装的是Nginx服务,那也不用担心,对此我们也可以额外安装这个工具。

htpasswd

安装htpasswd

sudo apt install apache2-utils

生成鉴权文件

htpasswd -bc .{domain}.pass {username} {password}

建议对生成的鉴权文件加上.进行基础隐藏操作,防止被扫描到

htpasswd命令详解

htpasswd命令详解

Nginx

配置文件

生成鉴权的文件后,我们要对需要加上的server域名下添加以下两条

 auth_basic "admin area"; # 启用鉴权
 auth_basic_user_file "/etc/nginx/http_auth/.{domain}.pass"; # 指定鉴权文件

添加完成后重启服务即可。

成果

成果

小提示

  • 建议对HTTP服务加上SSL证书,以防中间人窃听密码。

Nested是什么?

  • 直观的说,Nested实际上就是Object的

    数组

    。如下,这个user就是个nested结构

    {
    "user" : [ 
      {
        "first" : "John",
        "last" :  "Smith"
      },
      {
        "first" : "Alice",
        "last" :  "White"
      }
    ]
    }

Nested 和 Object 是什么关系?

  • ES原生支持Object类型,也就是任意字段都可以是个对象,而ES又是所有字段都是多值,也就是都可以是list。那么在ES中Nested和Object List又是什么关系呢?
  • 这就要从Object说起了。Object虽然是个对象,但是实际存储时是在当前文档里打平存储的。如上那个例子,如果只有一个user,那么在真实索引中实际上是下面这样的
{
  "user.first" : "John",
  "user.last" : "Smith"
}
  • 而如果是个list,那么就成了
{
  "user.first" : ["John","Alice"],
  "user.last" : ["Smith","White"]
}
  • 因为建索引时打平,因此检索时ES就无法知道到底是John Smith还是John White了。因此引入了Nested结构。
  • Nested将list里的每个doc单独变成子文档进行存储,因此在查询时就可以知道具体的结构信息了。

Nested 查询要注意什么?

  • Nested因为是单独的子文档存储,因此在使用时,直接用 a.b.c 是无法访问的,需要将其套在nested查询里。除此之外,和其他的查询并无差异。
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "match": {"user.first" : "John"}
      },
      "inner_hits": {}
    }
  }
}
  • 如上所示,用一个nested套住真实query即可。默认的hit是返回父文档,也就是大的doc。如果加上inner_hits会在父文档的source中多一个inner_hits的字段,返回真实命中的object,其中有个offset表明list数组下标。
  • 需要注意的是,由于单独存储很耗资源,因此默认一个index最多只有50个nested字段。此外,虽然nested是单独存储的,但是其字段数也算入index总字段数,默认最多1000个。

Nested Aggregation是什么?

  • 对于Nested结构,有一点需要谨记的,就是他是个List结构。Nested Agg就是对这个list做agg操作,agg写法和普通的一样,只需要在外面套上nested即可。
  • 如官方文档的例子,就是一个商品有许多卖家,对这些卖家的报价求最小值。

能否用Nested做动态kv?

  • Nested除了存储固定的Object List,还有一种常用的场景就是用来存储动态的KV。虽然ES天然支持dynamic mapping,但是其key都是固化在每一个doc中的,如果存储用户自定义报表数据。每个用户的key差异很大,放在同一张表会出现大量空值。这是很浪费系统资源的行为,并且随着Key的不断增多,最终会超出index的最大key数量。
  • 因此用nested结构来处理这种动态kv就比较合适。 nested的本质就是将 {"tags":{"k1":"v1","k2":"v2"}}=>{"tags":[{"key":"key1","value":"v1"},{"key":"key2","value":"v2"}]}
  • 这样一来就可以轻松处理动态kv。并且查询依旧简单,例如k1:v1 AND k2:v2变为
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "tags",
            "query": {
              "query_string": {
                "query": "tags.key:k1 AND tags.value:v1"
              }
            }
          }
        },
        {
          "nested": {
            "path": "tags",
            "query": {
              "query_string": {
                "query": "tags.key:k2 AND tags.value:v2"
              }
            }
          }
        }
      ]
    }
  }
}

动态kv如何做agg呢?

  • 普通查询的确很简单,但是agg就并不简单了。原来的模式可以直接用真实字段tags.k1做agg,但是在nested里k1已经变成了一个字段的值,因此没法直接做agg了。
  • 这时就需要引入script大法了。其实agg的本质就是从每个doc的正排里取一个值,用这个值做聚合。因此我们只需要用script遍历list,找到对应的key然后返回其value即可。
  • 简单写了个如下所示,如果有更好的方法欢迎留言。
  • 注意!!! 由于nested单独存储,因此doc里并没有nested数据,需要用params从source中拿。性能很差,仅可用于少量数据场景!
{ ...
  "aggs": {
    "test_agg": {
      "terms": {
        "script": {
          "inline": "for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']=='k1'){return params['_source']['tags'][i]['value']}}",
          "lang": "painless"
        },
        "size": 5
      }
    }
  }
}
  • 在使用中我们还可以把script存在来,来加速运算,减少缓存。(注意:5.6以后将code改为了source字段,具体写法参阅文档)
POST _scripts/is_tag_key
{
  "script":{
    "lang": "painless",
    "code":"for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']==params.key){return params['_source']['tags'][i]['value']}}"
  }
}
  • 这样用起来就简单多了
{ ...
  "aggs": {
    "test_agg": {
      "terms": {
        "script": {
          "stored": "is_tag_key",
          "params": {
            "key": "k1"
          }
        },
        "size": 5
      }
    }
  }
}

怎么在kibana里做agg呢?

  • kibana其实和上面的一样,也是用script.不过只支持inline的,在script field配置。不过注意一定不能太多,因为每一个inline script都是一个单独的script都需要消耗存储资源。

参考资料

文章来源