2015-10-29 2 views
0

У меня есть документ, в котором есть ученики и оценки для каждого ученика. Это выглядит примерно так:Фильтр Elasticsearch для определения отсутствия значения

"name": "bill", 
"year": 2015, 
"grades": [ 
    {"subject": "math", grade: "A"}, 
    {"subject": "english", grade: "B"} 
    ], ... 

Я ищу фильтр запроса (ов), которые могут дать мне:

  • список студентов, которые изучали «математика», и
  • список студентов, у которых есть нет изучал 'математику'.

Я имею в виду, что существует фильтр должен это сделать, но я изо всех сил, чтобы получить мою голову вокруг него.


Это стилизованный пример, но отображения являются чем-то вроде этого:

"mappings": { 
    "student": { 
     "properties": { 
      "name": { 
       "type": "string" 
      }, 
      "grades": { 
       "type": "nested", 
       "properties": { 
       "subject": { 
        "type": "string" 
       }, 
       "grade": { 
        "type": "string" 
       } 
       } 
      } 
     } 
    } 
    } 
+0

Не могли бы вы размещаете указательные отображения ? –

+0

@EvaldasBuinauskas - добавления добавлены. – pheobas

ответ

0

term filter должен делать только штрафом. Для обратного запроса, просто отрицать его с not filter:

"query": 
{ 
    "filtered" : { 
     "query": { 
      "match_all": {} 
     }, 
     "filter" : { 
      "term": { 
       "grades.subject": "math" 
      } 
     } 
    } 
} 

И для тех, кто не изучают математику:

"query": 
{ 
    "filtered" : { 
     "query": { 
      "match_all": {} 
     }, 
     "filter" : { 
      "not": { 
       "filter": { 
        "term": { 
         "grades.subject": "math" 
        } 
       } 
      } 
     } 
    } 
} 
+0

Это будет работать там, где классы - это один объект, но в моем случае классы - это массив. – pheobas

+0

@pheobas Вы пробовали? Я вполне уверен, что он работает, если я не понял ваш вопрос. У нас почти такой же случай (массив рабочих мест с аннотированной промышленностью). – Slomo

+0

Это сработало. Моя проблема заключалась в том, что у моих сопоставлений был подкласс документа, сопоставленный как «вложенный» тип, и это влияет на то, как запрашивается документ. Нужно читать об этом сейчас ... – pheobas

1

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

Во-первых, ваш nested объект должен быть "include_in_parent": true, так что вы можете легко сделать not studied 'math' часть:

PUT /grades 
{ 
    "mappings": { 
    "student": { 
     "properties": { 
     "name": { 
      "type": "string" 
     }, 
     "grades": { 
      "type": "nested", 
      "include_in_parent": true, 
      "properties": { 
      "subject": { 
       "type": "string" 
      }, 
      "grade": { 
       "type": "string" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

И полный запрос, используя скоплениями:

GET /grades/student/_search?search_type=count 
{ 
    "aggs": { 
    "studying_math": { 
     "filter": { 
     "nested": { 
      "path": "grades", 
      "query": { 
      "filtered": { 
       "filter": { 
       "bool": { 
        "must": [ 
        { 
         "term": { 
         "grades.subject": "math" 
         } 
        } 
        ] 
       } 
       } 
      } 
      } 
     } 
     }, 
     "aggs": { 
     "top_10": { 
      "top_hits": { 
      "size": 10 
      } 
     } 
     } 
    }, 
    "not_studying_math": { 
     "filter": { 
     "bool": { 
      "must_not": [ 
      { 
       "term": { 
       "grades.subject": "math" 
       } 
      } 
      ] 
     } 
     }, 
     "aggs": { 
     "top_10": { 
      "top_hits": { 
      "size": 10 
      } 
     } 
     } 
    } 
    } 
} 
Смежные вопросы