2015-09-10 6 views
0

Я работаю над реализацией эластичного элемента на сайте, над которым я работаю, и пытаюсь создать многодиапазонный фильтр. Есть 2 поля, которые имеют диапазоны, которые мне нужно будет фильтровать по: цене и рейтингу. Каждый из них должен иметь возможность выбирать сразу несколько диапазонов. Так, например, вы должны иметь возможность фильтровать по рейтингам 80-85 OR 90-95, а также фильтровать по цене 10-15 OR 20-25. Я использую post_filter для фильтров сроков и диапазонов, так как я строю гранвую навигацию для результатов поиска. Ниже вы можете увидеть мой структурированный json, который я отправляю.Elasticsearch фильтры нескольких диапазонов в одном и том же поле

{ 
    "from": 0, 
    "size": 15, 
    "query": { 
    "multi_match": { 
     "query": "taz 2003", 
     "type": "most_fields", 
     "operator": "or", 
     "fields": [ 
     "name", 
     "vintage", 
     "brand^4", 
     "review" 
     ], 
     "fuzziness": "1" 
    } 
    }, 
    "post_filter": { 
    "bool": { 
     "must": [ 
     { 
      "term": { 
      "vintage": "2009" 
      } 
     } 
     ], 
     "should": [ 
     { 
      "range": { 
      "price": { 
       "gte": 10, 
       "lt": 15 
      } 
      } 
     }, 
     { 
      "range": { 
      "price": { 
       "gte": 20, 
       "lt": 25 
      } 
      } 
     }, 
     { 
      "range": { 
      "rating": { 
       "gte": 80, 
       "lt": 85 
      } 
      } 
     }, 
     { 
      "range": { 
      "rating": { 
       "gte": 90, 
       "lt": 95 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

Это почти работает, однако, поскольку все диапазоны в пределах BOOL фильтра should, он использует OR объединить их, так что это только соответствие на одном из фильтров. Что мне нужно для того, чтобы сделать что-то вроде следующего (в SQL):

SELECT * FROM `table` where 
vintage = 2009 AND 
(
    (
     price BETWEEN 10 AND 15 OR 
     price BETWEEN 20 AND 25 
    ) AND 
    (
     rating BETWEEN 80 AND 85 OR 
     rating BETWEEN 90 AND 85 
    ) 
); 

Я теряюсь в данный момент, как это сделать. Заранее спасибо за помощь.

+1

ли вы попробовать положить все фильтры в '«должен»'? –

+0

Да, но это не вернет никаких результатов, поскольку компания не может иметь рейтинг между 80-85 и 90-95, а также с ценой – ZeLoubs

+0

О, я вижу. Должна быть способна вложить bools. Если вы разместите некоторые данные примера и желаемый результат, я увижу, смогу ли я это обработать. –

ответ

3

Один из способов будет использовать nested bool запрос в примере must

:

{ 
    "from": 0, 
    "size": 15, 
    "query": { 
    "multi_match": { 
     "query": "taz 2003", 
     "type": "most_fields", 
     "operator": "or", 
     "fields": [ 
     "name", 
     "vintage", 
     "brand^4", 
     "review" 
     ], 
     "fuzziness": "1" 
    } 
    }, 
    "post_filter": { 
    "bool": { 
     "must": [ 
     { 
      "term": { 
      "vintage": "2009" 
      } 
     }, 
     { 
      "bool": { 
      "should": [ 
       { 
       "range": { 
        "price": { 
        "gte": 10, 
        "lt": 15 
        } 
       } 
       }, 
       { 
       "range": { 
        "price": { 
        "gte": 20, 
        "lt": 25 
        } 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "bool": { 
      "should": [ 
       { 
       "range": { 
        "rating": { 
        "gte": 80, 
        "lt": 85 
        } 
       } 
       }, 
       { 
       "range": { 
        "rating": { 
        "gte": 90, 
        "lt": 95 
        } 
       } 
       } 
      ] 
      } 
     } 
     ] 
    } 
    } 
} 
+0

Да, это сделал трюк. Спасибо! – ZeLoubs

+0

Я пытался построить запрос с помощью Nest, который бы сгенерировал это, но в итоге просто запустил ORing вместе множество запросов фильтра диапазона в контейнер запроса, а затем ANDing с остальными моими фильтрами (которые сами также являются запросами контейнеры). – bsantisi

Смежные вопросы