如何在elasticsearch

时间:2017-09-07 16:16:11

标签: elasticsearch elasticsearch-mapping

在elasticsearch中存储关系数据的选项有哪些。我知道以下方法

  1. 嵌套对象: - 我不想以嵌套格式存储数据,因为我想更新一个文档而不更改其他文档,如果我使用嵌套对象那么在父文件中会有重复的子数据。

  2. 亲子: - 我不想将数据存储在单个索引中,但是对于使用父子数据需要存在于一个索引中(不同类型) 。我知道这个限制将在https://github.com/elastic/elasticsearch/issues/15613问题中提到的将来版本中删除,但我想要一个适用于5.5版本的解决方案。

  3. 除此之外还有其他方法。

2 个答案:

答案 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)

还有两种方法:Denormalizationrunning multiple queries for joins

非规范化将占用更多空间并增加您的写入时间,但您只需运行一个查询来检索数据,因此,您的阅读时间将得到改善。由于您不希望将数据存储在单个索引中,因此加入可能会帮助您解决问题。