2013-07-23 2 views
1

шин позволяет создать запрос elasticsearch с использованием DSL, предназначенный для отражения API JSON, например:Составляя запрос шины из нескольких блоков рубина

search = Tire::Search::Search.new 

search.query do 
    boolean do 
    should { match :title, "Red" } 
    should { match :synopsis, "Red" } 
    should { match :brand_title, "Red" } 
    end 

    boolean do 
    must { term :excluded, false } 
    end 
end 

Я хотел бы разделить на это в мой собственный DSL для определения групп запросов, которые могут быть построены, вроде Rails прицелов:

class Proxy 
    def initialize 
    @queries = [] 
    end 

    def results 
    search = Tire::Search::Search.new 
    queries = @queries 

    search.query do 
     # …? What should go here to search the combined set of conditions? 
    end 
    end 

    def term t 
    query do 
     boolean do 
     should { match :title, t } 
     should { match :synopsis, t } 
     should { match :brand_title, t } 
     end 
    end 
    end 

    def included bool 
    query do 
     boolean do 
     must { term :excluded, !bool } 
     end 
    end 
    end 

    private 
    def query &block 
    @queries << block 
    end 
end 

p = Proxy.new 

p.term "Red" 
p.included true 

p.results 

проблема заключается в том, Тир не позволяет более одного search.query блока - последующие query s заменить предыдущую. Можно ли использовать нечто вроде instance_eval для запуска нескольких блоков в правильном контексте блока запроса?

ответ

0

Оказывается, что блоки просто можно запустить instance_eval и они выполняются в правильном контексте:

def results 
    search = Tire::Search::Search.new 
    queries = @queries # Only local variables are available inside the query block below 

    search.query do 
    queries.each do |q| 
     instance_eval(&q) 
    end 
    end 
end 

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

+0

Любая идея, если бы это работало с фильтрами вроде: term? Я попробовал, бит кажется, что только последний proc будет отправлен экземпляром instance_eval'd. Спасибо. – brupm

0

Я не знаком с шиной, но имею опыт в elasticsearch Query DSL. Я думаю, проблема заключается в том, что API поиска допускает только один "query": {...} в JSON, который отправляется на конечную точку _search.

Подумайте об этом, если у вас было несколько запросов, как elasticsearch знает, как их объединить. Для этого вам нужно использовать другой запрос bool.

"query" является корнем (возможно большого) дерева запросов, у вас не может быть более одного корня!

Надежда Я мог бы помочь ...

+0

Спасибо, я думаю, что я доволен этим ограничением. Возможно, заголовок вводит в заблуждение, но я был бы очень рад найти способ в Ruby, чтобы создать один единственный запрос, но с помощью отдельных вызовов метода Ruby. – Gareth

+0

Я не могу помочь с рубином. Боюсь, но я сделал что-то подобное в php с эластикой (эквивалент шины). У меня были методы, которые добавляли к запросу root 'bool' (к предложению' must' или 'should', добавляя запрос в конец массива. Что-то вроде 'function addShould ($ newQuery) {$ this-> should [] = $ newQuery; } ' – ramseykhalaf

0

Это объясняется в документации. Проверьте здесь http://karmi.github.io/tire/#section-84.

Вы можете назвать их как

Tire.search('articles') { query { boolean &tags_query } } 

и просто создавать свои собственные лямбды.