使用kibana对文档操作

437 阅读4分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

新增文档

文档,即索引库中某个类型下的数据,会根据规则创建索引,将来用来搜索。可以类比做数据库中的每一行数据。

新增并随机生成id

通过POST请求,可以向一个已经存在的索引库中添加文档数据。

语法:

POST /索引库名/类型名
{
    "key":"value"
}

示例:

POST /lagou/goods/
{
    "title":"小米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":2699.00
}

响应:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "tURGznQB29tVfg_iWHfl",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 3,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 2
}

可以看到结果显示为:created,应该是创建成功了。

另外,需要注意的是,在响应结果中有个_id字段,这个就是这条文档数据的唯一标示,以后的增删改查都依赖这个id作为唯一标示。

可以看到id的值为:tURGznQB29tVfg_iWHfl ,这里我们新增时没有指定id,所以是ES帮我们随机生成的id。

查看文档

根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把刚刚生成数据的id带上。

通过kibana查看数据:

GET /lagou/goods/tURGznQB29tVfg_iWHfl

查看结果:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "tURGznQB29tVfg_iWHfl",
    "_version": 1,
    "found": true,
    "_source": {
        "title": "小米手机",
        "images": "http://image.lagou.com/12479122.jpg",
        "price": 2699
    }
}
  • _source:源文档信息,所有的数据都在里面。
  • _id:这条文档的唯一标示
  • 自动生成的id,长度为20个字符,URL安全,base64编码,GUID(全局唯一标识符),分布式系统并行生成时不可能会发生冲突
  • 在实际开发中不建议使用ES生成的ID,太长且为字符串类型,检索时效率低。建议:将数据表中唯一的ID,作为ES的文档ID

新增文档并自定义id

如果我们想要自己新增的时候指定id,可以这么做:

POST /索引库名/类型/id值
{
    ...
}

示例:

POST /lagou/goods/2
{
    "title":"大米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":2899.00
}

得到的数据:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "2",
    "_score": 1,
    "_source": {
        "title": "大米手机",
        "images": "http://image.lagou.com/12479122.jpg",
        "price": 2899
    }
}

修改数据

PUT:修改文档

POST:新增文档

把刚才新增的请求方式改为PUT,就是修改了。不过修改必须指定id,

  • id对应文档存在,则修改
  • id对应文档不存在,则新增

比如,我们把使用id为3,不存在,则应该是新增:

PUT /lagou/goods/3
{
    "title":"超米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":3899.00,
    "stock": 100,
    "saleable":true
}

结果:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "3",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}

可以看到是created,是新增。

我们再次执行刚才的请求,不过把数据改一下:

PUT /lagou/goods/3
{
    "title":"超大米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":3299.00,
    "stock": 100,
    "saleable":true
}

查看结果:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "3",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 2,
    "_primary_term": 1
}

可以看到结果是:updated,显然是更新数据

删除数据

删除使用DELETE请求,同样,需要根据id进行删除:

语法

DELETE /索引库名/类型名/id值

示例:

image.png

智能判断

刚刚我们在新增数据时,添加的字段都是提前在类型中定义过的,如果我们添加的字段并没有提前定义过,能够成功吗?

事实上Elasticsearch非常智能,你不需要给索引库设置任何mapping映射,它也可以根据你输入的数据来判断类型,动态添加数据映射。

测试一下:

POST /lagou/goods/3
{
    "title":"超大米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":3299.00,
    "stock": 200,
    "saleable":true,
    "subTitle":"大米"
}

我们额外添加了stock库存,saleable是否上架,subtitle副标题、3个字段。

来看结果:

{
    "_index": "lagou",
    "_type": "goods",
    "_id": "3",
    "_version": 3,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 3,
    "_primary_term": 1
}

成功了!在看下索引库的映射关系:

image.png

stock、saleable、subtitle都被成功映射了。

subtitle是String类型数据,ES无法智能判断,它就会存入两个字段。例如:

  • subtitle:text类型
  • subtitle.keyword:keyword类型

这种智能映射,底层原理是动态模板映射,如果我们想修改这种智能映射的规则,其实只要修改动态模板即可!

动态映射模板

动态模板的语法:

image.png

  1. 模板名称,随便起
  2. 匹配条件,凡是符合条件的未定义字段,都会按照这个规则来映射
  3. 映射规则,匹配成功后的映射规则

举例,我们可以把所有未映射的string类型数据自动映射为keyword类型:

PUT lagou3
{
    "mappings": {
        "goods": {
            "properties": {
                "title": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                }
            },
            "dynamic_templates": [
                {
                    "strings": {
                        "match_mapping_type": "string",
                        "mapping": {
                            "type": "keyword",
                            "index":false,
                            "store":true
                        }
                    }
                }
            ]
        }
    }
}

在这个案例中,我们把做了两个映射配置:

  • title字段:统一映射为text类型,并制定分词器
  • 其它字段:只要是string类型,统一都处理为keyword类型。

这样,未知的string类型数据就不会被映射为text和keyword并存,而是统一以keyword来处理!

我们试试看新增一个数据:

POST /lagou3/goods/1
{
    "title":"超大米手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":3299.00
}

我们只对title做了配置,现在来看看images和price会被映射为什么类型呢:

GET /lagou3/_mapping

结果:

{
    "lagou3": {
        "mappings": {
            "goods": {
                "dynamic_templates": [
                    {
                        "strings": {
                            "match_mapping_type": "string",
                            "mapping": {
                                "type": "keyword"
                            }
                        }
                    }
                ],
                "properties": {
                    "images": {
                        "type": "keyword"
                    },
                    "price": {
                        "type": "float"
                    },
                    "title": {
                        "type": "text",
                        "analyzer": "ik_max_word"
                    }
                }
            }
        }
    }
}

可以看到images被映射成了keyword,而非之前的text和keyword并存,说明我们的动态模板生效了!