elasticsearch支持大table格式数据的搜索
一、问题源起
数据情况
TableMeta, 保存table的元数据,通过fileId关联具体的GridFS文件;
| id | name | creator | fileId |
|---|---|---|---|
| 1 | table1 | mango | f1 |
| 2 | table2 | mango | f2 |
table内包含列名和具体的行数据;
不同类型的table,列的名字和数量都可能不同;
from fport to toport location
192.168.1.1 11 192.168.1.12 11 chaoyang
192.168.1.2 22 192.168.1.13 22 tongzhou
搜索要求
支持所有类型的table的搜索;
支持全字段的搜索;
只返回表内命中的行,并进行高亮;
二、开发环境
elasticsearch 6.8.12
java 12.0.2 2019-07-16
Java(TM) SE Runtime Environment (build 12.0.2+10)
Java HotSpot(TM) 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)
三、elastic search对array的支持情况
扁平化数组元素
默认情况下elastic search会将数组内部对象的字段进行扁平化处理,这样就会丢失掉元素的独立性。
直接index一个文档
PUT my_array_index/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
{
"_index":"my_array_index",
"_type":"_doc",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{
"total":2,
"successful":1,
"failed":0
},
"_seq_no":0,
"_primary_term":1
}
elastic search 内部会将文档转化为如下形式再进行索引
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
扁平化处理将所有数组元素对象的相同字段值合并到一起作为一个数组,这样就丢失了user.first和user.last之间的对应关系,类似下边的查询即使没有Alice Smith这个人也可以命中
GET my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
{
"took":2,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":1,
"max_score":0.5753642,
"hits":[
{
"_index":"my_array_index",
"_type":"_doc",
"_id":"1",
"_score":0.5753642,
"_source":{
"group":"fans",
"user":[
{
"first":"John",
"last":"Smith"
},
{
"first":"Alice",
"last":"White"
}
]
}
}
]
}
}
使用nested数据类型文档化数组元素
elastic search内部提供了nested数据类型,可以将数组元素作为单独的隐藏的内部文档进行索引,从而保持文档之间的独立性;
将字段映射为nested类型
PUT my_nested_index
{
"mappings": {
"_doc": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
}
{
"acknowledged":true,
"shards_acknowledged":true,
"index":"my_nested_index"
}
index文档
PUT my_nested_index/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
{
"_index":"my_nested_index",
"_type":"_doc",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{
"total":2,
"successful":1,
"failed":0
},
"_seq_no":0,
"_primary_term":1
}
elastic search提供了单独的nested query 来支持nested类型
GET my_nested_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
}
}
{
"took":3,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":0,
"max_score":null,
"hits":[
]
}
}
nested query提供了inner_hits类支持字段高亮,从高亮信息中可以看到,offset字段指出了命中了数组中的第几个元素;
GET my_nested_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"should": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "smith" }}
]
}
},
"inner_hits": {
"highlight": {
"fields": {
"*": {}
}
}
}
}
}
}
{
"took":8,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":1,
"max_score":0.6931472,
"hits":[
{
"_index":"my_nested_index",
"_type":"_doc",
"_id":"1",
"_score":0.6931472,
"_source":{
"group":"fans",
"user":[
{
"first":"John",
"last":"Smith"
},
{
"first":"Alice",
"last":"White"
}
]
},
"inner_hits":{
"user":{
"hits":{
"total":2,
"max_score":0.6931472,
"hits":[
{
"_index":"my_nested_index",
"_type":"_doc",
"_id":"1",
"_nested":{
"field":"user",
"offset":0
},
"_score":0.6931472,
"_source":{
"first":"John",
"last":"Smith"
},
"highlight":{
"user.last":[
"<em>Smith</em>"
]
}
},
{
"_index":"my_nested_index",
"_type":"_doc",
"_id":"1",
"_nested":{
"field":"user",
"offset":1
},
"_score":0.6931472,
"_source":{
"first":"Alice",
"last":"White"
},
"highlight":{
"user.first":[
"<em>Alice</em>"
]
}
}
]
}
}
}
}
]
}
}
总结
经过以上的研究可以看到,elastic search提供的nested数据类型基本满足我们的目标要求,接下来使用具体的table数据做进一步的研究;
四、使用nested数据类型索引Table数据
elastic search索引数据结构
| 字段名字 | 字段类型 | 描述 |
|---|---|---|
| id | string | 主键 |
| name | string | table的名字 |
| creator | string | 创建者 |
| content | (object) array | 行数据数组 |
elastic search mapping
PUT tables
{
"mappings": {
"_doc": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"creator": {
"type": "keyword"
},
"content": {
"type": "nested"
}
}
}
}
}
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "tables"
}
index 一个Table data
PUT tables/_doc/1
{
"id":"1",
"name":"table1",
"creator":"mango",
"content":[
{
"0":"192.168.1.1",
"1":"11",
"2":"192.168.1.12",
"3":"11",
"4":"chaoyang"
},
{
"0":"192.168.1.2",
"1":"22",
"2":"192.168.1.13",
"3":"22",
"4":"tongzhou"
},
{
"0":"192.168.3",
"1":"33",
"2":"192.168.1.14",
"3":"33",
"4":"daxing"
}
]
}
{
"_index":"tables",
"_type":"_doc",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{
"total":2,
"successful":1,
"failed":0
},
"_seq_no":0,
"_primary_term":1
}
search Table data
搜索所有列
限制只返回Table的元数据信息
限制只返回命中行的信息
返回命中行的高亮信息
post /tables/_search/
{
"from":0,
"size":20,
"_source":{
"excludes":[
"content"
]
},
"query":{
"nested":{
"path":"content",
"query":{
"query_string":{
"fields":[
"content.*"
],
"query":"tongzhou 192.168.1.1"
}
},
"inner_hits":{
"from":0,
"size":2,
"highlight":{
"fields":{
"*":{
}
}
}
}
}
}
}
{
"took":19,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":1,
"max_score":0.9808292,
"hits":[
{
"_index":"tables",
"_type":"_doc",
"_id":"1",
"_score":0.9808292,
"_source":{
"creator":"mango",
"name":"table1",
"id":"1"
},
"inner_hits":{
"content":{
"hits":{
"total":2,
"max_score":0.9808292,
"hits":[
{
"_index":"tables",
"_type":"_doc",
"_id":"1",
"_nested":{
"field":"content",
"offset":0
},
"_score":0.9808292,
"_source":{
"0":"192.168.1.1",
"1":"11",
"2":"192.168.1.12",
"3":"11",
"4":"chaoyang"
},
"highlight":{
"content.0":[
"<em>192.168.1.1</em>"
]
}
},
{
"_index":"tables",
"_type":"_doc",
"_id":"1",
"_nested":{
"field":"content",
"offset":1
},
"_score":0.9808292,
"_source":{
"0":"192.168.1.2",
"1":"22",
"2":"192.168.1.13",
"3":"22",
"4":"tongzhou"
},
"highlight":{
"content.4":[
"<em>tongzhou</em>"
]
}
}
]
}
}
}
}
]
}
}
elasticsearch支持大table格式数据的搜索的更多相关文章
- 导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件
小程序导入,别人导出的数据库json文件,错误信息如下: 导入数据库失败, Error: Poll error, 导入数据任务(id:373985)异常,错误信息:解析导入文件错误,请检查导入文件内容 ...
- 使用ElasticSearch服务从MySQL同步数据实现搜索即时提示与全文搜索功能
最近用了几天时间为公司项目集成了全文搜索引擎,项目初步目标是用于搜索框的即时提示.数据需要从MySQL中同步过来,因为数据不小,因此需要考虑初次同步后进行持续的增量同步.这里用到的开源服务就是Elas ...
- PetaPoco轻量级ORM框架 - 对Database类的进行扩展,可以返回Table格式数据
一.有时我们需要将常用的功能添加到PetaPoco中的Database类中 实现方式有2种,以下以查询字段为例 1.通过扩展方式实现,此方式不改变被调用(Database)类名(只能增加方法) pub ...
- SpringBoot RestController 同时支持返回xml和json格式数据
@RestController 默认支持返回json格式数据,即使不做任何配置也能返回json数据 当接口需要支持xml或json两种格式数据时应该怎么做呢? 只要引入 Jackson xml的 ma ...
- 分享一个jquery写的类似于百度的搜索框,(可动态配置,可单列或者table格式,可填充数据)
需求:类似于百度的搜索框,可配置,可单列可table格式,可填充数据.页面可多次使用,简单,易用. 想法:使用jquery,css,ajax,前台调用,后台返回json数据. jquery代码: va ...
- C# winfrom 写的一个搜索助手,可以按照标题和内容搜索,支持doc,xls,ppt,pdf,txt等格式的文件搜索
C# winfrom 写的一个搜索助手,可以按照标题和内容搜索,指定目录后,遍历搜索文件和子目,现在只写了支持.DOC.DOCX.XLS.XLSX.PPT.PPTX.PDF.HTML.HTM.TXT等 ...
- 【ElasticSearch】ES 读数据,写数据与搜索数据的过程
ES读数据的过程: 1.ES客户端选择一个node发送请求,该请求作为协调节点(coordinating node): 2.corrdinating node 对 doc id 对哈希,找出该文档对应 ...
- 使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索
使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索 2015-03-26 dotNET跨平台 最近几年出现的云计算为组织和用户带来了福音.组织对客户的了解达到前所未有的透彻, ...
- elasticsearch最全详细使用教程:搜索详解
一.搜索API 1. 搜索API 端点地址从索引tweet里面搜索字段user为kimchy的记录 GET /twitter/_search?q=user:kimchy从索引tweet,user里面搜 ...
随机推荐
- swagger json导出word,Typora软件推荐!!!
场景: 前几天项目验收,赶了一整天补API接口设计文档,给爷整吐了.周末的时候就想能不能直接把swagger的json文件导出成word? 顺便学习一下NPOI的使用. 实现思路: 1.先把swaag ...
- 【译】使用 Source Link 提高调试效率
有多少次你在调试器中追踪一个缺陷,通过代码,观察局部变量的值改变,当你碰壁--不是你所期待的值和你不能进入的方法,因为它来自类库或 .NET 框架本身:或者您设置了一个条件断点,等待检查某个值是如何设 ...
- 自建简易FaaS平台
近些年来,传统的 IaaS.PaaS 已经无法满足人们对资源调度的需求了.各大云厂商相继开始推出自家的 Serverless 服务.Serverless 顾名思义,它是"无服务器" ...
- 承载童年的游戏机,已停产!但我在 GitHub 找到了它们
那些年,上网用的是电话线,小企鹅也只会笨拙地左右摇晃,手机还只是打电话的工具.虽然那些年没有互联网,但游戏机承载了我的童年. 小时候我老是追着我的两个哥哥,他们带我玩了好多种游戏机,比如街机.红白机. ...
- 除了Swagger UI,你还能选择 IGeekFan.AspNetCore.RapiDoc
IGeekFan.AspNetCore.RapiDoc 看到博客园上的这个文章,说了下Knife4J,评论里有人推荐RapiDoc,放了几个图,看了下,还不错. 心里 便有个想法,借着上次研究 Kni ...
- 双非本科字节跳动Android面试题分享(已拿offer)
基本情况 本人系非985非211普通本科生一枚,有实习有项目经历但成绩普通,在面试前刷了很多面经.面试题,这里也把自己的分享下,做个回报好了,顺便攒攒人品,一到这种时候人就迷信起来了. 面试是以视频面 ...
- BBPlayerView
GitHub 仓库地址 一个高度封装的视频播放器视图,基于 AVPlayer.AVPlayerLayer.AVPlayerItem. 继承自 UIView,可以当做一般视图使用,适用于 Swift 和 ...
- Java compareTo() 方法(转载)
Java compareTo() 方法 compareTo() 方法用于两种方式的比较: 字符串与对象进行比较. 按字典顺序比较两个字符串. 语法: int compareTo(Object o)// ...
- 用SamInside破解Windows登录密码
用小马PE的USB-HDD+格式制作启动优盘: 笔记本启动时按ESC键,选择USB启动: 进入WinPE后,将%SystemRoot%/system32/config全部拷贝出来(WinXP这个文件夹 ...
- Shell-02-数据类型
shell数据类型 shell常用的数据类型有 字符串.整数型.数组 字符串 字符串是shell编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号 建议使用双引号,因为双 ...