ElasticSearch

데이터 검색

엔꾸꾸 2020. 7. 18. 14:57

서론

 

 

엘라스틱서치는 인덱스에 저장된 문서를 검색할 수 있도록 다양한 검색 기능 을 제공 한다.

색인 시점 뿐 아니라 검색 시점에도 분석기 를 사용하며 점수 (score) 를 매겨 순서를 적용한다.

 

 

검색 질의 표현방식

 

검색 API 는 기본적으로 질의 (Query) 를 기반으로 동작한다.

검색 질의는 URI 검색Request Body 검색 두 가지로 표현할 수 있다.

 

 

URI 검색

 

HTTP GET 요청을 활용하는 방식으로 쿼리스트링 을 활용해 파라메터를 전달한다.

Request Body 방식에 비해 단순하고 사용하기 편리하지만, 복잡한 질의문을 입력이 제한된다.

// 요청
curl -XGET http://localhost:9200/teams/_search?q=creator:ncucu

// 결과
{
   "took":2,
   "timed_out":false,
   "_shards":{
      "total":1,
      "successful":1,
      "skipped":0,
      "failed":0
   },
   "hits":{
      "total":{
         "value":1,
         "relation":"eq"
      },
      "max_score":0.6931471,
      "hits":[
         {
            "_index":"teams",
            "_type":"team",
            "_id":"1",
            "_score":0.6931471,
            "_source":{
               "title":"TalkStore",
               "creator":"ncucu",
               "date":"2020-06-17",
               "memberCount":110
            }
         }
      ]
   }
}

 

URI 검색은 엘라스틱서치 에서 제공하는 모든 검색 옵션을 사용할 수 없다.

 

RequestBody 검색

 

HTTP 요청 시 Body 에 검색할 칼럼과 검색어를 JSON 형태로 표현해서 전달하는 방식이다.

이를 좀 더 효율적으로 하기 위해 Query DSL 이라는 문법을 지원 한다.

 

위의 URI 방식에서 검색 했던 질의를 Request Body 방식으로 변경할 경우 다음과 같다.

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/teams/_search?pretty -d '
{
	"query": {
		"query_string": {
			"default_field": "creator",
			"query": "ncucu"
		}
	}
}
'

// 응답
{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.6931471,
    "hits" : [
      {
        "_index" : "teams",
        "_type" : "team",
        "_id" : "1",
        "_score" : 0.6931471,
        "_source" : {
          "title" : "TalkStore",
          "creator" : "ncucu",
          "date" : "2020-06-17",
          "memberCount" : 110
        }
      }
    ]
  }
}

 

URI 검색 보다는 Request Body 방식을 사용 하자.

 

 

Query DSL

 

Query DSL 을 이용하면 여러 개의 질의를 조합하거나, 질의 결과 대해 다시 검색을 수행 하는 등 정밀한 검색 이 가능해 진다.

 

 

Query DSL의 구조

 

JSON 구조를 기반으로 하고 있으며, 정해진 문법에 따라 JSON 구조를 작성해야 한다.

// 요청
{
	// 리턴받는 결과의 개수 지정. default = 10
	"size" :

	// 몇 번째 문서부터 가져올지 지정. default = 0
	"from" :

	// 검색요청 timeout. default = unlimit
	"timeout" :

	// 검색 시 필요한 필드만 출력하고 싶을 때 사용
	"_source" : {}

	// 검색 조건문이 들어가는 공간
	"query" : {}

	// 통계 및 집계 데이터를 사용할 때 
	"aggs" : {}

	// 문서 결과를 어떻게 출력할지에 대한 조건을 사용하는 공간
	"sort" : {}
}

// 응답
{
	// 쿼리 실행한 시간
	"took":

	// 쿼리 시간이 초과할 경우 나타냄
	"timed_out":

	"_shards": {
		// 쿼리 요청한 전체 샤드 개수
		"total":
		// 겁색 요청에 성공적으로 응답한 샤드 개수
		"successful":
		// 검색 요청에 실패한 샤드 개수
		"failed":
	},

	"hits": {
		// 검색 매칭된 문서의 전체 개수
		"total":
		// 일치하는 문서의 스코어 값 중 가장 높은 값
		"max_score":
		// 각 문서 정보와 스코어 값
		"hits": []
	}
}

 

만약 JSON 문법에 오류가 있다면 json_parse_exception 을 포함한 응답을 받는다.

 

 

쿼리 컨텍스트와 필터 컨텍스트의 차이

 

QueryDSL에는 Query와 Filter가 있는데, 분석기를 이용한 전문 분석이 필요한 경우 Query를, 단순히 Yes/No 와 같은 조건 검색이 필요한 경우 Filter를 사용한다.

엘라스틱서치에서 전자의 경우 쿼리 컨텍스트, 후자의 경우 필터 컨텍스트 라고 한다.

  쿼리 컨텍스트 필터 컨텍스트
용도 전문 검색 조건 검색
특징 분석기에 의해 분석이 수행됨. 연관성 관련 Scope를 계산. 루씬 레벨에서 분석 과정을 거쳐야 하므로 상대적으로 느림 (결과가 캐싱되지 않음) Yes/No로 단순 판별 가능. 연관성 관련 계산을 하지 않음. 엘라스틱서치 레벨에서 처리가 가능하므로 상대적으로 빠름 (결과를 내부적으로 캐싱함)
사용 예시 "Harry Potter" 같은 문장 분석 "create_year" 필드의 값이 2018년인지 여부 등

 

 

Query DSL 주요 파라미터

 

Multi Index 검색

  • 검색 요청 시 콤마 ( , ) 를 이용해 복수 인덱스 검색이 가능하다.
  • 와일드카드 ( * ) 를 사용할 수 있다.
curl XPOST -H 'Content-Type: application/json' http://localhost:9200/movie_search,movie_auto/_search -d '
{
	"query" : {
		"term": {
			"repGenreNm": "다큐멘터리"
		}
	}
}
'

 

쿼리 결과 페이징

  • from, size 파라메터를 이용하면 되지만 5건씩 페이징한 2 페이지 요청시 5개가 아닌, 10개의 문서를 로드한다는 점에 유의
// 첫번째 페이지 요청
curl XPOST -H 'Content-Type: application/json' http://localhost:9200/movie_search/_search -d '
{
	"from":0,
	"size":5,
	"query" : {
		"term": {
		"repNationNm": "한국"
		}
	}
}'

// 두번째 페이지 요청
curl XPOST -H 'Content-Type: application/json' http://localhost:9200/movie_search/_search -d '
{
	"from":5,
	"size":5,
	"query" : {
		"term": {
		"repNationNm": "한국"
		}
	}
}'

 

쿼리 결과 정렬

  • 기본적으로 계산한 유사도 score 값으로 정렬하는것 외에 필드, 날짜 등으로 재정렬 하고 싶을때 사용한다.
  • asc, desc 옵션을 제공한다.
{
	"sort" : {
		"prdtYear": {
			"order": "asc"
		}
	}
}

 

_source 필드 필터링

  • 쿼리시 특정 필드만 검색 결과에 포함하도록 필터링이 가능하다.
  • SQL Projection 과 동일
{
	"_source" : {
		"movieNm"
}

 

범위 검색

  • 범위 검색이 가능한 파라메터를 제공한다.
문법 연산자 설명
lt < 피연산자 보다 작음
gt > 피연산자 보다 큼
lte <= 피연산자 보다 작거나 같음
gte >= 피연산자 보다 크거나 같음

 

operator 설정

  • 검색 시 문장이 들어올 경우 기본적으로 OR 연산 이 적용된다.
  • operator 파라미터를 활용하여 명시적으로 and 또는 or 연산을 적용할 수 있다.
  • 파라미터 생략시에는 or 연산이 적용된다.
{
	"query" : {
		"match": {
			"creator": {
				"query": "헬로헬로 안녕안녕",
				"operator": "and"
			}
		}
	}
}

 

minumum_should_match 설정

  • OR 연산을 수행할 경우 검색 결과가 너무 많아 지는데, 텀의 개수가 몇 개 이상 매칭될 때 검색 결과로 포함시킨다.
  • 텀의 개수와 minimum_should_match 옵션의 값을 일치시키면 AND 와 비슷하게 동작 한다.
{
	"query" : {
		"match": {
			"creator": {
				"query": "헬로헬로 안녕안녕",
				"minimum_should_match": 2
			}
		}
	}
}

 

fuzziness 설정

  • 유사한 값을 Fuzzy Query로 변경 할 수 있다.
  • 레벤슈타인의 편집 거리 알고리즘을 기반으로 문서의 필드 값을 여러번 변경하는 방식으로 동작한다.
// 오차범위 한글자 이하인 검색 결과까지 포함
{
	"query" : {
		"match": {
			"creator": {
				"query": "헬로헬로 안녕안녕",
				"fuzniness": 2
			}
		}
	}
}

 

boost 설정

  • 특정 필드에 가중치를 줄 때 사용한다.
  • 검색에서 가장 많이 사용하는 파라미터 중 하나
// movieNm에 가중치를 3만큼 곱한다.
{
	"query" : {
		"multi_match": {
				"query": "헬로헬로 안녕안녕",
				"fields": ["movieNm^3", "movieNmEn"]
		}
	}
}

 

 

Query DSL 주요 쿼리

 

 

Match All Query

  • match_all 파라미터 사용
  • 색인에 존재하는 모든 문서를 검색하는 쿼리
  • 일반적으로 색인에 저장된 문서 확인 시 사용된다.
{
	"query" : {
		"match_all": {}
	}
}

 

Match Query

  • 형태소 분석을 통해 텀으로 분리한 후 이를 이용해 검색을 질의한다.
  • 검색어 분석이 필요할 경우 사용해야 한다.
{
	"query" : {
		"match": {
			"movieNm": "그대 장미"
		}
	}
}

 

Multi Match Query

  • Match Query와 기본 사용방법은 동일하다.
  • 여러 개의 필드를 대상으로 검색 할 때 사용한다.
{
	"query" : {
		"multi_match": {
			"query": "가족",
			"fields": ["movieNm", "movieNmEn"]
		}
	}
}

 

Term Query

  • 별도 분석 작업을 수행하지 않는다.
  • Keyword 데이터 타입 필드 검색시 사용한다.
{
	"query" : {
		"term": {
			"genreAlt": "코미디",
		}
	}
}

 

Bool Query

  • 여러 개의 쿼리를 조합하여 더 높은 스코어를 가진 쿼리 조건으로 검색 수행이 가능하다.
  • 이를 Compound Query 라고 한다.
  • Compound Query를 구현하기 위해 Bool Query를 제공한다.
{
	"query" : {
		"bool": {
			// AND 
			"must" : [],
			// NOT
			"must_not": [],
			// OR
			"should": [],
			// IN ()
			"filter": []
		}
	}
}

 

Query String

  • 기본 내장된 쿼리 분석기를 이용하는 질의 이다.
{
	"query" : {
		"query_string": {
			"default_field": "movieNm",
			// 공백은 연산자로 사용되지 않음 '어린이 날' 로 검색됨
			"query": "(가정) AND (어린이 날)"
		}
	}
}

 

Prefix Query

  • 해당 접두어가 존재하는 모든 문서를 검색 한다.
  • 역색인 된 텀 들을 스캔하여 검색한다.
{
	"query" : {
		"prefix": {
			// '자전차'로 시작하는 문서를 검색한다
			"movieNm": "자전차",
		}
	}
}

 

Exists Query

  • 필드 값이 null 이 아닌 문서를 검색 한다.
{
	"query" : {
		"exists": {
			// movieNm 필드가 null이 아닌 문서를 검색
			"field": "movieNm",
		}
	}
}

 

Wildcard Query

  • 검색어가 와일드카드와 일치한 구문을 찾는다.
  • Term level Query (형태소분석 X)
  • *: 문자 길이와 상관없이 모든 문서를 찾는다.
  • ?: 지정한 위치의 한 글자와 다른 경우의 문서를 찾는다.
{
	"query" : {
		"wildcard": {
			"creator": "ncuc?",
		}
	}
}

 

Nested Query

  • 관계형 데이터베이스의 조인과 유사한 기능
  • Nested 데이터 타입의 필드 검색시 사용한다.
{
	// Nested Query를 이용해 문서의 companies 필드 안에 companyCd 코드를 매칭해 조회한다.
	"nested" : {
		"path": "companies", 
		"query": {
			"bool": {
				"must": [
					{
						"term": {
							"companies.companyCd": "20173401"
						}
					}
				}
			}
		}
	}
}

 

 

부가적인 검색 API

 

엘라스틱서치는 대량의 데이터 처리를 위해 기본적으로 분산 저장한다.

 

검색 요청시 프로세스

  1. 검색 요청시 모든 샤드에 요청을 브로드캐스팅하여 전달후 대기한다.
  2. 각 샤드는 자신이 가진 데이터를 기준으로 수행 결과를 반환한다.
  3. 모든 샤드로 부터 도착한 결과를 조합하여 최종 결과를 출력한다.

 

동적 분배 방식의 샤드 선택

  • 검색 수행시 중복된 결과 전달을 방지하기 위해 동일 데이터를 가진 샤드 중 하나만 선택해 검색을 수행한다.
  • 기본 설정은 라운드 로빈 방식의 알고리즘
  • 동적 분배 방식은 검색 요청의 응답시간, 수행하는 스레드 풀의 크기 등을 고려한 최적의 샤드를 결정

 

글로벌 타임아웃 설정

 

개별 검색 요청 시 Request Body에 직접 타임아웃을 설정하거나 글로벌 설정이 가능하다.

글로벌 설정의 기본 정책은 무한정 대기 ( -1 ) 이다.

curl -XPUT -H 'Content-Type: application/json' http://localhost:9200/_cluster/settings -d '
{
	"transient" : {
		"search.default_search_timeout": "1s"
	}
}
'

 

Search Shards API

 

검색이 수행되는 노드 및 샤드에 대한 정보 확인시 사용한다.

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/teams/_search_shards?pretty

// 응답
{
  "nodes" : {
    "8h8cJZBXRhe3GbKvvu8BNw" : {
      "name" : "ncucu-1",
      "ephemeral_id" : "mcRrrU0IQgi98SiotdyHdQ",
      "transport_address" : "127.0.0.1:9300",
      "attributes" : {
        "ml.machine_memory" : "1927020544",
        "xpack.installed" : "true",
        "transform.node" : "true",
        "ml.max_open_jobs" : "20"
      }
    }
  },
  "indices" : {
    "teams" : { }
  },
  "shards" : [
    [
      {
        "state" : "STARTED",
        "primary" : true,
        "node" : "8h8cJZBXRhe3GbKvvu8BNw",
        "relocating_node" : null,
        "shard" : 0,
        "index" : "teams",
        "allocation_id" : {
          "id" : "fu3h220jTZ2lEmAiZQTxPg"
        }
      }
    ]
  ]
}

 

Multi Search API

 

여러 건의 검색 요청을 한번에 요청하고 한번에 결과를 조합하여 받을때 사용한다.

여러 인덱스에 사용자 별 특화된 정보를 가져올 때 유용하다.

POST _msearch
{"index" : "movie_auto"}
{"query" : {"match_all" : {}}, "from" : 0, "size" : 10}
{"index" : "movie_search"}
{"query" : {"match_all" : {}}, "from" : 0, "size" : 10}

 

Count API

 

검색된 문서의 개수만 필요한 경우 사용한다.

URI 검색/ RequestBody 검색 모두 지원한다.

 

URI 검색

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/teams/_count?q=creator:ncucu

//응답
{"count":1,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}

 

Request Body 검색

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/teams/_count?pretty -d '
{
	"query": {
		"query_string": {
			"default_field": "creator",
			"query": "ncucu"
		}
	}
}
'

// 응답
{
  "count" : 1,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  }
}

 

 

Validate API

 

쿼리가 유효한지 검증하는 기능을 제공하는 API

URI 검색/Request Body 검색에서 모두 지원한다.

 

URI 검색

// 요청
curl -XPOST http://localhost:9200/_validate/query?q=creator:ncucu

// 응답
{"_shards":{"total":11,"successful":11,"failed":0},"valid":true}

 

Request Body 검색

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/_validate/query?pretty -d '
{
	"query": {
		"match": {
			"creator": "ncucu"
		}
	}
}
'

// 응답
{
  "_shards" : {
    "total" : 11,
    "successful" : 11,
    "failed" : 0
  },
  "valid" : true
}

 

쿼리에 오류가 있다면 valid의 값이 false 이다. 쿼리 실패 이유를 상세하게 알고 싶다면 rewrite=true 파라메터를 추가하자.

 

Explain API

 

특정 문서에 대해 요청한 쿼리가 어떻게 스코어 계산되었는지 확인이 가능하다.

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/teams/team/1/_explain?pretty -d '
{
	"query": {
		"term": {
			"creator": "ncucu"
		}	
	}
}
'

// 응답
{
  "_index" : "teams",
  "_type" : "team",
  "_id" : "1",
  "matched" : true,
  "explanation" : {
    "value" : 0.6931471,
    "description" : "weight(creator:ncucu in 0) [PerFieldSimilarity], result of:",
    "details" : [
      {
        "value" : 0.6931471,
        "description" : "score(freq=1.0), computed as boost * idf * tf from:",
        "details" : [
          {
            "value" : 2.2,
            "description" : "boost",
            "details" : [ ]
          },
          {
            "value" : 0.6931472,
            "description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
            "details" : [
              {
                "value" : 1,
                "description" : "n, number of documents containing term",
                "details" : [ ]
              },
              {
                "value" : 2,
                "description" : "N, total number of documents with field",
                "details" : [ ]
              }
            ]
          },
          {
            "value" : 0.45454544,
            "description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
            "details" : [
              {
                "value" : 1.0,
                "description" : "freq, occurrences of term within document",
                "details" : [ ]
              },
              {
                "value" : 1.2,
                "description" : "k1, term saturation parameter",
                "details" : [ ]
              },
              {
                "value" : 0.75,
                "description" : "b, length normalization parameter",
                "details" : [ ]
              },
              {
                "value" : 1.0,
                "description" : "dl, length of field",
                "details" : [ ]
              },
              {
                "value" : 1.0,
                "description" : "avgdl, average length of field",
                "details" : [ ]
              }
            ]
          }
        ]
      }
    ]
  }
}

 

Profile API

 

쿼리에 대한 수행 계획을 확인할 수 있다.

// 요청
curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/_search?pretty -d '
{
	"profile": true,
	"query": {
		"match_all": {}
	}
}
'

// 응답
{
  "took" : 46,
  "timed_out" : false,
  "_shards" : {
    "total" : 15,
    "successful" : 15,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "books",
        "_type" : "book",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "field" : "value"
        }
      },
      {
        "_index" : "orders",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : "test",
          "date" : "2020-01-01"
        }
      },
      {
        "_index" : "teams",
        "_type" : "team",
        "_id" : "1_update",
        "_score" : 1.0,
        "_source" : {
          "script" : "if(ctx._source.creator.contains(name)) { ctx._source.memberCount = 100 } else { ctx._source.memberCount = 200}",
          "params" : {
            "name" : "cucu"
          }
        }
      },
      {
        "_index" : "teams",
        "_type" : "team",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "TalkStore",
          "creator" : "ncucu",
          "date" : "2020-06-17",
          "memberCount" : 110
        }
      },
      {
        "_index" : "teams",
        "_type" : "team",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "title" : "채널개발파트",
          "creator" : "ryan",
          "date" : "2020-06-15",
          "memberCount" : 10
        }
      },
      {
        "_index" : "dev_analyzer",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "Harry Poter and the Chamber of Secrets"
        }
      }
    ]
  },
  "profile" : {
    "shards" : [
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][books][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1009757,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 2167,
                  "match" : 0,
                  "next_doc_count" : 1,
                  "score_count" : 1,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 7893,
                  "advance_count" : 1,
                  "score" : 2058,
                  "build_scorer_count" : 2,
                  "create_weight" : 2021,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 995612
                }
              }
            ],
            "rewrite_time" : 3156,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 35465
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_af_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 33242,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 33241,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1498,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 4080
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 3294,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 3293,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 13818,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 2556
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_analyzer][1]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1949,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1948,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1623,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 794
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_analyzer][2]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1652,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1651,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1518,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 767
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_analyzer][3]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1703,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1702,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1550,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 735
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_analyzer][4]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 12271,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 1089,
                  "match" : 0,
                  "next_doc_count" : 1,
                  "score_count" : 1,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 1172,
                  "advance_count" : 1,
                  "score" : 578,
                  "build_scorer_count" : 2,
                  "create_weight" : 1565,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 7861
                }
              }
            ],
            "rewrite_time" : 1484,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 7163
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_engram_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 3643,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 3642,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 2164,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 1369
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_html_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 2634,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 2633,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 2307,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 846
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_ngram_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 3460,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 3459,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 2251,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 1272
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][dev_stop_analyzer][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1899,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1898,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1695,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 796
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][movie_search][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1827,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1826,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1807,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 800
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][orders][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 16084,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 1207,
                  "match" : 0,
                  "next_doc_count" : 1,
                  "score_count" : 1,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 1547,
                  "advance_count" : 1,
                  "score" : 633,
                  "build_scorer_count" : 2,
                  "create_weight" : 1924,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 10767
                }
              }
            ],
            "rewrite_time" : 1684,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 8466
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][teams][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 37347,
                "breakdown" : {
                  "set_min_competitive_score_count" : 1,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 6254,
                  "next_doc" : 3326,
                  "match" : 0,
                  "next_doc_count" : 3,
                  "score_count" : 3,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 2922,
                  "advance_count" : 3,
                  "score" : 1391,
                  "build_scorer_count" : 6,
                  "create_weight" : 2021,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 21416
                }
              }
            ],
            "rewrite_time" : 1669,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 49149
              }
            ]
          }
        ],
        "aggregations" : [ ]
      },
      {
        "id" : "[8h8cJZBXRhe3GbKvvu8BNw][tests][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "MatchAllDocsQuery",
                "description" : "*:*",
                "time_in_nanos" : 1920,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 0,
                  "match" : 0,
                  "next_doc_count" : 0,
                  "score_count" : 0,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 0,
                  "build_scorer_count" : 0,
                  "create_weight" : 1919,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 0
                }
              }
            ],
            "rewrite_time" : 1588,
            "collector" : [
              {
                "name" : "SimpleTopScoreDocCollector",
                "reason" : "search_top_hits",
                "time_in_nanos" : 730
              }
            ]
          }
        ],
        "aggregations" : [ ]
      }
    ]
  }
}