Elasticsearch——利用Parent-Child关系解决大数据场景下的实时查询

原创 2017年02月07日 23:58:33

表与表之间的关联基本上是所有业务系统都存在的,RDBMS通过外键实现,MongoDB通过嵌入式子文档解决,那么Elasticsearch怎么解决这个问题呢?答案就是Parent-Child关联(参考文档

业务场景

有一个广告的分发系统,为了更精准的做广告的推送,除了自身积累的数据以外,还会从其他合作方通过数据交换(当然这些都是脱敏的数据)的方式获取更多用户行为数据,例如从音乐网站获取听的音乐列表、从购物网站获取最近的购物类别、从书评网站获取最近浏览的图书等等。这些来自于外部的数据,有以下几个问题:

  1. 并不是每个用户都有全部的数据,比如有些用户只有书评和音乐信息,而有些用户没有任何外部信息
  2. 某一类外部的数据源可能包含几个网站,比如音乐网站有A、B、C三个网站,它们提供的数据格式也并不一致

在进行广告推送时,需要实时查询一个用户的信息完成精准推荐。比如实时查询满足下面条件的用户:

  • 最近一个月,
  • 经常在早上、傍晚或者晚上连续一个小时的音乐;
  • 购买过跑鞋、运动手表等跑步装备
  • 且购买过或点评过运动类书籍

再继续下面的(十分简化)解决方案之前,可以先思考下

解决方案

这是典型应用大数据进行个性化精准推荐的应用场景,在省却了数据清洗、评分等各种步骤以后,简化为一个查询问题。分析可以发现数据问题的核心就是:无固定表结构,是典型的Schema-Free的NoSQL应用场景,第一个反应出来的就是MongoDB。

MongoDB

MongoDB用作以上的数据存储,毫无疑问具有天然的优势,可以将每个来源的数据都作为user的一个子文档存储,查询时也只是在这一个Collection上进行(可能有人会说这种方案太蠢了,的确是,不过也要看产品所处的阶段)。当然这样做的问题也显而易见:
为了查询速度,索引是必须要创建的。可是因为数据源不断变化,那么索引的维护就会变成一个灾难。一旦忘记创建查询,可能就会拖死整个系统。

下面当然就是主角上场了。

Elasticsearch

定调:
1. 由于字段是变化,因此必须使用动态Mapping(文档
2. 由于Parent-Child的关系需要创建索引(Create Index)时就确定,因此必须使用固定的Mapping(文档

我又检查了上面两条,的确是没有说错。

其实很简单,在创建索引时,只需指定父子关系,无需指定其他未知字段。因为要预先指定type的父子关系,所以就必须先确定type。这是用两个type:user和user_action,那么创建索引时的Mapping大致如下:

{
  "mappings": {
    "user": {},
    "user_action": {
      "_parent" : {
        "type": "user"
      }
    }
  }
}

我好像把文档中的例子抄了一遍,不多实际情况的确是这样。

那么在添加文档到索引中时,对于user就需要指定id,而user_action需要指定parent,例如:

es = Elasticsearch()

_id = 27
_user = {
  'id': 27,
  'name': 'Tigger Fei'
}

# 索引用户文档
es.index(index='user_index', doc_type='user', id=str(_id), body=_user)

# 索引用户行为文档, type字段表示列表
# 音乐
_music = {
  'type': 'music',
  'user': 27,
  'period': 'morning',
  'duration': 78,
  'category': 'running',
  'time': '2017-01-29 12:30:00'
}
es.index(index='user_index', doc_type='user_action', parent=str(_id), body=_music)
# 图书,
_book = {
  'type': 'book,'
  'user': 27,
  'name': '我的第一个马拉松',
  'category': 'running',
  'time': '2017-01-30 12:30:00'
}
es.index(index='user_index', doc_type='user_action', parent=str(_id), body=_book)

如何完成上面的查询呢,如下:

POST user_index/user/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "has_child": {
            "type": "user_action",
            "query": { 
              "bool": { 
                "filter": [
                  {"term": {"type": "music"}},
                  {"range": {"duration": {"gte": 60}}},
                  {"range": {
                    "time": {
                      "gte": "2017-01-07 00:00:00",
                      "format": "yyyy-MM-dd HH:mm:ss"
                     }
                   }},
                  {"term": {"category": "running"}},
                  {"terms": {"period": ["morning", "night"]}}
                ]
              }
            }
          }
        },
        {
          "has_child": {
            "type": "user_action",
            "query": { 
              "bool": { 
                "filter": [
                  {"range": {
                    "time": {
                      "gte": "2017-01-07 00:00:00",
                      "format": "yyyy-MM-dd HH:mm:ss"
                     }
                   }},
                  {"term": {"type": "book"}},
                  {"term": {"category": "running"}}
                ]
              }
            }
          }
        }
      ]
    }
  }
}

好了,这个简单的解决方案就完了。

版权声明:原创文章,欢迎转载,转载请注明出处和原文链接

理解elasticsearch的parent-child关系

前面文章介绍了,在es里面的几种数据组织关系,包括array[object],nested,以及今天要说的Parent-Child。 Parent-Child与Nested非常类似,都可以用来处...
  • u010454030
  • u010454030
  • 2017年09月04日 18:54
  • 901

elasticsearch mapping 学习(parent-child)

ES 父子文档查询 父子文档的特点 1. 父/子文档是完全独立的。 2. 父文档更新不会影响子文档。 3. 子文档更新不会影响父文档或者其它子文档。 父子...
  • qq_24365213
  • qq_24365213
  • 2018年02月02日 10:22
  • 31

elasticsearch 大数据优化

亿级规模的Elasticsearch优化实战 腾讯网 | 2015-08-13 17:51 本文根据王卫华老师在“高可用架构”微信群所做的《Elasticsearch实战经验分...
  • an74520
  • an74520
  • 2015年08月14日 14:57
  • 10680

elasticsearch的准实时(near real-time)查询

elasticsearch是基于lucene的,lucene是可以做到实时的,就是创建索引之后,立即能查询到。 但是这样,要么是牺牲索引的效率,每次都索引之后都刷新,要么就是牺牲查询的效率每次查询之...
  • hong0220
  • hong0220
  • 2016年04月08日 15:46
  • 1109

elasticsearch数据导入导出

1,elasticsearch导入json格式数据,代码如下: try { //读取刚才导出的ES数据 BufferedReader br = new BufferedReade...
  • lln_avaj
  • lln_avaj
  • 2017年03月01日 11:08
  • 258

实时搜索引擎Elasticsearch(3)——查询API的使用

上一篇文章介绍了ES中的Rest API,本章将重点介绍ES中的查询API的使用。由于笔者在实际项目仅仅将ES用作索引数据库,并没有深入研究过ES的搜索功能。而且鉴于笔者的搜索引擎知识有限,本文将仅仅...
  • xialei199023
  • xialei199023
  • 2015年09月05日 17:58
  • 14849

大数据实时流统计实战

Spark Streaming实时流处理项目 请访问:http://www.roncoo.com/course/view/1b1a07091acc4efd9a390f28db332f86 Sp...
  • zhaorui2017
  • zhaorui2017
  • 2017年12月08日 15:37
  • 567

Elasticsearch大数据处理技术在车牌识别系统中的测试研究

摘要 :为了提升车牌识别系统中海量数据的车辆特征与涉案车辆及交通违法信息的实时分析、布控与跟踪的响应时间与性能。本文在对传统技术分析的基础上,针对现有系统中无法实现大数据分析与处理的问题,提出了利用E...
  • likui1314159
  • likui1314159
  • 2016年06月21日 11:15
  • 1746

elasticsearch mapping 学习

elasticsearch中关于parent-child结构mapping的学习
  • lsk12162012
  • lsk12162012
  • 2015年12月14日 18:44
  • 888

大数据实时处理-基于Spark的大数据实时处理及应用技术

培训要点 互联网点击数据、传感数据、日志文件、具有丰富地理空间信息的移动数据和涉及网络的各类评论,成为了海量信息的多种形式。当数据以成百上千TB不断增长的时候,我们在内部交易系统的历史信息之外,需要...
  • shenmanli
  • shenmanli
  • 2016年03月11日 14:57
  • 1552
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Elasticsearch——利用Parent-Child关系解决大数据场景下的实时查询
举报原因:
原因补充:

(最多只允许输入30个字)