在elasticsearch中存储关系数据的选项有哪些。我知道以下方法
嵌套对象: - 我不想以嵌套格式存储数据,因为我想更新一个文档而不更改其他文档,如果我使用嵌套对象那么在父文件中会有重复的子数据。
亲子: - 我不想将数据存储在单个索引中,但是对于使用父子数据需要存在于一个索引中(不同类型) 。我知道这个限制将在https://github.com/elastic/elasticsearch/issues/15613问题中提到的将来版本中删除,但我想要一个适用于5.5版本的解决方案。
除此之外还有其他方法。
答案 0 :(得分:4)
嵌套对象是一种完美的方法。如果正确更新子对象,则父文档中不会重复子对象。 我在我的一个用例中使用相同的方法,我需要维护Master-Child One-to-Many关系的关系数据。 我已经为更新API 写了无痛脚本到添加& 更新父文档中现有的嵌套子对象,而不会创建重复或重复的条目。
更新答案:
以下是具有嵌入式嵌套类型文档" childs"的父子嵌套类型文档的结构。
{
"parent_id": 1,
"parent_name": "ABC",
"parent_number": 123,
"parent_addr": "123 6th St. Melbourne, FL 32904"
"childs": [
{
"child_id": 1,
"child_name": "PQR",
"child_number": 456,
"child_age": 10
},
{
"child_id": 2,
"child_name": "XYZ",
"child_number": 789,
"child_age": 12
},
{
"child_id": 3,
"child_name": "QWE",
"child_number": 234,
"child_age": 16
}
]
}
映射如下:
PUT parent/
{
"parent": {
"mappings": {
"parent": {
"properties": {
"parent_id": {
"type": "long"
},
"parent_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"parent_number": {
"type": "long"
},
"parent_addr": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"child_tickets": {
"type": "nested",
"properties": {
"child_id": {
"type": "long"
},
"child_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"child_number": {
"type": "long"
},
"child_age": {
"type": "long"
}
}
}
}
}
}
}
}
在RDMS中,这两个实体(父级,子级)是两个不同的表,父级之间具有一对多关系 - >儿童。 父母的id是Child的行的外键。 (两个表必须是id)
现在在Elasticsearch中,要索引父文档,我们必须有id来索引它,在这种情况下它是parent_id。 索引父文档查询(parent_id是我正在讨论的id,并且索引具有id(_id)= 1的文档):
POST parent/parent/1
{
"parent_id": 1,
"parent_name": "ABC",
"parent_number": 123,
"parent_addr": "123 6th St. Melbourne, FL 32904"
}
现在,将子项添加到父项。为此,您将需要子文档,该文档应具有子ID和父ID。 要添加子项,必须使用父ID。以下是添加新子项或更新已存在的子项的更新查询。
POST parent/parent/1/_update
{
"script":{
"lang":"painless",
"inline":"if (!ctx._source.containsKey(\"childs\")) {
ctx._source.childs = [];
ctx._source.childs.add(params.child);
} else {
int flag=0;
for(int i=0;i<ctx._source.childs.size();i++){
if(ctx._source.childs[i].child_id==params.child.child_id){
ctx._source.childs[i]=params.child;
flag++;
}
}
if(flag==0){
ctx._source.childs.add(params.child);
}
}",
"params":{
"child":{
"child_id": 1,
"child_name": "PQR",
"child_number": 456,
"child_age": 10
}
}
}
}
试一试。干杯!
如果您还有其他需要,请告诉我。
答案 1 :(得分:2)
还有两种方法:Denormalization和running multiple queries for joins。
非规范化将占用更多空间并增加您的写入时间,但您只需运行一个查询来检索数据,因此,您的阅读时间将得到改善。由于您不希望将数据存储在单个索引中,因此加入可能会帮助您解决问题。