Как искать в родительских документах вместе с количеством связанных дочерних документов - PullRequest
0 голосов
/ 19 апреля 2020

Я ищу лучший способ поиска родительских документов вместе с количеством связанных дочерних документов? Пример: У нас есть организационные документы и пользовательские документы. Там могут быть тысячи пользователей, принадлежащих к одной конкретной организации.

Документ организации:

{
   "id" : "001"
   "name" : "orgname1"
}
{
   "id" : "002"
   "name" : "orgname2"
}

Документы пользователей:

{
   "id" : "testusr1"
   "name" : "xyz1"
   "orgId" : "001"
},
{
   "id" : "testusr2"
   "name" : "xyz2"
   "orgId" : "001"
}
{
   "id" : "testusr3"
   "name" : "xyz3"
   "orgId" : "001"
}
{
   "id" : "testusr4"
   "name" : "xyz4"
   "orgId" : "001"
}
{
   "id" : "testusr5"
   "name" : "xyz5"
   "orgId" : "002"
}
{
   "id" : "testusr6"
   "name" : "xyz6"
   "orgId" : "002"
}

В приведенном выше примере у нас есть 4 пользователя, связанные с организацией с 001, и 2 пользователя, связанные с 002. Поэтому на переднем крае администратор будет искать организацию, и в результате я хочу дать ответ вместе с количеством пользователей для этой организации.

1 Ответ

0 голосов
/ 20 апреля 2020

Вы можете решить свою проблему тремя способами. У каждого есть свои преимущества и недостатки

1. Индекс Родитель и потомок отдельно

Для этого потребуется два запроса. Сначала вам нужно запросить индекс пользователя и получить orgId, а затем запросить дочерний индекс и получить его счет

Advantage.

Изменение одного индекса не влияет на другой индекс

Недостаток .

Вам нужно использовать два запроса

2. Вложенные документы

Отображение:

PUT index9
{
  "mappings": {
    "properties": {
      "id":{
        "type": "integer"
      },
      "name":{
        "type": "text",
        "fields": {
          "keyword":{
            "type":"keyword"
          }
        }
      },
      "user":{
        "type": "nested",
        "properties": {
          "id":{
            "type":"text",
            "fields":{
              "keyword":{
              "type":"keyword"
              }
            }
          },
          "name":{
            "type":"text",
            "fields":{
              "keyword":{
              "type":"keyword"
              }
            }
          }
        }
      }
    }
  }
}


POST index9/_doc
{
  "id" : 1,
  "name" : "orgname1",
  "user":[
           {
             "id":"testuser1",
             "name":"xyz1"
           },
           {
             "id":"testuser2",
             "name":"xyz2"
           }
         ]
}

Запрос:

GET index9/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "organization": {
      "terms": {
        "field": "id",
        "size": 10
      },
      "aggs": {
        "user": {
          "nested": {
            "path": "user"
          },
          "aggs": {
            "count": {
              "value_count": {
                "field": "user.id.keyword"
              }
            }
          }
        }
      }
    }
  }
}

Результат:

"aggregations" : {
    "organization" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 1,
          "doc_count" : 1,
          "user" : {
            "doc_count" : 2,
            "count" : {
              "value" : 2
            }
          }
        }
      ]
    }
  }

Вложенные быстрее по сравнению с родительским / дочерним, вложенные документы требуют переиндексации родительского элемента со всеми его дочерними элементами, в то время как родительский дочерний элемент позволяет переиндексировать / добавить / удалить указанных c дочерних элементов.

3. Родительско-дочерние отношения

Отображение

{
  "my_index" : {
    "mappings" : {
      "properties" : {
        "id" : {
          "type" : "keyword"
        },
        "my_join_field" : {
          "type" : "join",
          "eager_global_ordinals" : true,
          "relations" : {
            "organization" : "user"
          }
        },
        "name" : {
          "type" : "text"
        },
        "orgId" : {
          "type" : "long"
        }
      }
    }
  }

Данные:

POST my_index/_doc/1
{
  "id": 1,
  "name" : "orgname1",
  "my_join_field": "organization" 
}

POST my_index/_doc/2
{
  "id" : 2,
  "name" : "orgname2",
  "my_join_field": "organization" 
}

POST my_index/_doc/3?routing=1
{
  "id": "testusr1",
  "name": "xyz1",
  "orgId": 1,
  "my_join_field": {
    "name": "user",
    "parent": 1
  }
}

POST my_index/_doc/4?routing=2
{
   "id" : "testusr5",
   "name" : "xyz5",
   "orgId" : 1,
   "my_join_field": {
    "name": "user",
    "parent": 2
  }
}

POST my_index/_doc/5?routing=2
{
   "id" : "testusr6",
   "name" : "xyz6",
   "orgId" : 2,
   "my_join_field": {
    "name": "user",
    "parent": 2
  }
}

Запрос:

{
  "query": {
    "has_child": {
      "type": "user",
      "query": { "match_all": {} }
    }
  },
  "aggs": {
    "organization": {
      "terms": {
        "field": "id",
        "size": 10
      },
      "aggs": {
        "user": {
          "children": {
            "type": "user"
          },
          "aggs": {
            "count": {
              "value_count": {
                "field": "id"
              }
            }
          }
        }
      }
    }
  }
}

Результат:

"hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "name" : "orgname1",
          "my_join_field" : "organization"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "name" : "orgname2",
          "my_join_field" : "organization"
        }
      }
    ]
  },
  "aggregations" : {
    "organization" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "1",
          "doc_count" : 1,
          "user" : {
            "doc_count" : 1,
            "count" : {
              "value" : 1
            }
          }
        },
        {
          "key" : "2",
          "doc_count" : 1,
          "user" : {
            "doc_count" : 2,
            "count" : {
              "value" : 2
            }
          }
        }
      ]
    }

Преимущества: 1. Родительский документ и дети являются отдельными документами

Родитель и дочерний элемент могут обновляться отдельно без повторного индексирования другого

Это полезно, когда дочерние документы имеют большое количество и их необходимо часто добавлять или изменять.

Дочерние документы могут быть возвращены в результате запроса на поиск.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...