# -*- coding: utf-8 -*- # copyright 2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr -- mailto:contact@logilab.fr # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 2.1 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from compiler.ast import flatten from elasticsearch_dsl import Q def compose_search(query): ''' Compose a elasticsearch-dsl query from queries : * simple term * simple terms (OR) * negation (add - in front of a term) * explicit OR * quoted terms (AND) ''' # FIXME TODO - restructure entier code base, have a proper lexer must = [] must_not = [] should = [] if '"' in query: elements = flatten([x.split() for x in query.split('"') if x]) elif "'" in query: elements = flatten([x.split() for x in query.split("'") if x]) else: elements = query.split() elements_lowercase = [e.lower() for e in elements] if 'or' in elements_lowercase and len(elements) >= 3: for element in query.split('or'): should.append(Q('multi_match', query=element.strip(), fields=())) elements = [] elif '-' not in query: elements = [' '.join(elements)] for element in elements: if element.startswith('-'): must_not.append(Q('multi_match', query=element[1:], fields=())) else: must.append(Q('multi_match', query=element, fields=())) return Q('bool', must=must, must_not=must_not, should=should)