ElasticSearch——nested(mapping,query,aggregation)

15520 단어 Elasticsearch
ElasticSearch는 nested 필드 유형을 포함하는데 이 유형의 출현은 주로 대상 수조 유형의 조작이 우리가 예상한 대로 되지 않기 때문이다. 이것은 주로 Lucene 내부에 대상의 개념이 없기 때문에 ES는 등급의 JSON 데이터를 납작한 키 값 대열 표형식으로 전환시킨다.
예를 들어 문서:
PUT my_index/my_type/5
{
  "owner" : " ",
  "family" : [
    {
      "call" : "dad",
      "name" :  " "
    },
    {
      "call" : "mom",
      "name" :  " "
    }
  ]
}

전환 후 실제로는 다음과 같습니다.
PUT my_index/my_type/5
{
  "owner": " ",
  "family.call": [
    "dad",
    "mom"
  ],
  "family.name": [
    " ",
    " "
  ]
}

이렇게 되면 아버지의 이름이 이취련이라고 검색해도 결과가 나올 수 있다는 것은 분명히 우리의 예상과 맞지 않는다.
그러나 ES의 nested 형식 필드는 대상 그룹의 모든 대상이 독립된 색인과 조회를 할 수 있도록 합니다.
우리는 먼저 일반적인 처리 방식을 만들어서 어떤 결과를 얻을 수 있는지 보았다.

nest를 사용하지 않는 예:


동적 맵핑을 사용하여 데이터를 직접 삽입합니다. 대상 그룹 맵핑의 데이터 형식은 대상 형식입니다.

1단계: 데이터 추가:

PUT my_index/my_type/1
{
  "owner": " ",
  "family": [
    {
      "call": "dad",
      "name": " "
    },
    {
      "call": "mom",
      "name": " "
    }
  ]
}
PUT my_index/my_type/2
{
  "owner" : " ",
  "family" : [
    {
      "call" : "dad",
      "name" :  " "
    },
    {
      "call" : "mom",
      "name" :  " "
    }
  ]
}
PUT my_index/my_type/3
{
  "owner" : " ",
  "family" : [
    {
      "call" : "dad",
      "name" :  " "
    },
    {
      "call" : "mom",
      "name" :  " "
    }
  ]
}

PUT my_index/my_type/4
{
  "owner" : " ",
  "family" : [
    {
      "call" : "dad",
      "name" :  " "
    },
    {
      "call" : "mom",
      "name" :  " "
    }
  ]
}

PUT my_index/my_type/5
{
  "owner" : " ",
  "family" : [
    {
      "call" : "dad",
      "name" :  " "
    },
    {
      "call" : "mom",
      "name" :  " "
    }
  ]
}
위쪽, 색인 라이브러리 my_index의 표 my_type 데이터 5개 추가

2단계:mapping 결과 보기

{
  "my_index": {
    "mappings": {
      "my_type": {
        "properties": {
          "family": {
            "properties": {
              "call": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "name": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          },
          "owner": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}
family는 대상 유형에 두 개의 속성을 포함하는 것을 볼 수 있습니다.

3단계 질의:


must+term 조회
GET my_index/my_type/_search
{
 "query": {
   "bool": {
     "must": [
       {
         "term": {
           "family.name.keyword": " "
         }
       }, {
         "term": {
           "family.call.keyword": "dad"
         }
       }
     ]
   }
 }
}
돌아오지 않을 것으로 예상됩니다. 왜냐하면 아버지의 이름이 왕오모라는 사람이 없기 때문입니다.
실제 반환 결과는 다음과 같습니다.
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "3",
        "_score": 0.5753642,
        "_source": {
          "owner": " ",
          "family": [
            {
              "call": "dad",
              "name": " "
            },
            {
              "call": "mom",
              "name": " "
            }
          ]
        }
      }
    ]
  }

4단계: 모으기, 모든 아빠의 통계 얻기

GET my_index/my_type/_search?size=0
{
  "aggs": {
    "call": {
      "filter": {
        "term": {
          "family.call.keyword": "dad"
        }
      },
      "aggs": {
        "name": {
          "terms": {
            "field": "family.name.keyword",
            "size": 10
          }
        }
      }
    }
  }
}
아빠 5명의 통계를 기대했는데 실제로는 엄마의 이름도 되돌아왔다
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "call": {
      "doc_count": 5,
      "name": {
        "doc_count_error_upper_bound": 0,
        "sum_other_doc_count": 0,
        "buckets": [
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          },
          {
            "key": " ",
            "doc_count": 1
          }
        ]
      }
    }
  }
}
대상 그룹에 대해 특별한 처리를 하지 않으면 그 결과는 기대에 부합되지 않는다는 것을 알 수 있다.

다음은 nested와 관련된 조작 예입니다.


첫 번째 단계: 필드 형식에 따라 동적 맵을 할 수 없습니다. 대상 그룹 형식을nested 형식으로 변경해야 합니다.


동적 매핑을 위한 템플릿을 만들 수 있습니다.
모형판을 만들기 전에 테스트의 편의를 위해 원래의 상기 예에서 테스트 데이터를 삭제하고 다시 시작합니다.
삭제 실행: DELETE my_index
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "object_as_nest": {
            "match_mapping_type": "object",
            "mapping": {
              "type": "nested"
            }
          }
        }
      ]
    }
  }
}
그러면 대상 형식은nested 형식으로 비치고 다른 필드는 기본 동적 맵에 따라 비칩니다.

두 번째 단계: 데이터 추가 (대량 또는 조목조목 삽입 가능)


여기서 생략하겠습니다.
위의 예에서 첫 번째 삽입 동작을 사용하여 데이터를 추가합니다
다섯 개의 데이터를 얻다.

3단계: 매핑 결과 보기:

{
  "my_index": {
    "mappings": {
      "my_type": {
        "dynamic_templates": [
          {
            "object_as_nest": {
              "match_mapping_type": "object",
              "mapping": {
                "type": "nested"
              }
            }
          }
        ],
        "properties": {
          "family": {
            "type": "nested",
            "properties": {
              "call": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "name": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          },
          "owner": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

패밀리 타입이 네스티드로 변하는 걸 볼 수 있어요.

4단계: 아빠 이름 조회는'왕오모'와 같고, 결과가 돌아오지 않을 것으로 예상됩니다.


nested+must+term
GET my_index/my_type/_search
{
  "query": {
    "nested": {
      "path": "family",
      "score_mode": "sum",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "family.call.keyword": "dad"
              }
            },
            {
              "term": {
                "family.name.keyword": " "
              }
            }
          ]
        }
      }
    }
  }
}
결과 반환:
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

아빠 이름 조회는'장삼아빠'와 같다.
GET my_index/my_type/_search
{
  "query": {
    "nested": {
      "path": "family",
      "score_mode": "sum",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "family.call.keyword": "dad"
              }
            },
            {
              "term": {
                "family.name.keyword": " "
              }
            }
          ]
        }
      }
    }
  }
}
검색 결과: 하나의 결과와 예상 결과가 일치합니다.
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.3862944,
    "hits": [
      {
        "_index": "my_index",
        "_type": "my_type",
        "_id": "1",
        "_score": 1.3862944,
        "_source": {
          "owner": " ",
          "family": [
            {
              "call": "dad",
              "name": " "
            },
            {
              "call": "mom",
              "name": " "
            }
          ]
        }
      }
    ]
  }
}

다섯 번째 단계: 집합=모든 아빠 이름


nested+filter+term+terms 집합 방식
GET my_index/my_type/_search?size=0
{
  "aggs": {
    " ": {
      "nested": {
        "path": "family"
      },
      "aggs": {
        " ": {
          "filter": {
            "term": {
              "family.call.keyword": "dad"
            }
          },
          "aggs": {
            " ": {
              "terms": {
                "field": "family.name.keyword",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}
집계 결과는 다음과 같습니다.
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    " ": {
      "doc_count": 10,
      " ": {
        "doc_count": 5,
        " ": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            }
          ]
        }
      }
    }
  }
}

모든 엄마의 이름을 모으기:
GET my_index/my_type/_search?size=0
{
  "aggs": {
    " ": {
      "nested": {
        "path": "family"
      },
      "aggs": {
        " ": {
          "filter": {
            "term": {
              "family.call.keyword": "mom"
            }
          },
          "aggs": {
            " ": {
              "terms": {
                "field": "family.name.keyword",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

모든 엄마의 이름을 모은 결과;
{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    " ": {
      "doc_count": 10,
      " ": {
        "doc_count": 5,
        " ": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            },
            {
              "key": " ",
              "doc_count": 1
            }
          ]
        }
      }
    }
  }
}

이상에서 얻은 결과는 기대에 완전히 부합된다.
그리고 상대적으로 간단하다. 특히 동적 맵핑 템플릿의 구축도 그렇다.

좋은 웹페이지 즐겨찾기