def test_fuzzy(): eq_(str(Q(fuzzy='fuzzi')), 'fuzzi~') try: Q(fuzzy='test fuzz') except: pass else: raise AssertionError("Fuzzy queries shouldn't have whitespace.") eq_(str(Q(fuzzy=('fuzzi', .2))), 'fuzzi~0.200') eq_(str(Q('field', fuzzy='fuzzi')), 'field:(fuzzi~)')
def test_field_restrictions(): q1 = Q('field', 'test query') assert q1.fielded q2 = Q('a') & q1 assert q2.fielded try: Q('another_field', q2) except: pass else: raise AssertionError('Query allowed nested fields, which are invalid.')
def _get_filtered_nodes(self, lookups, label=None, include_properties=None): # Working on indices idx = self.node_index.neoindex q = Q(r"graph", r"%s" % self.graph_id) if label: q &= Q(r"label", r"%s" % label) for lookup in lookups: l = Q() if lookup["lookup"] == "contains": l |= Q(r"%s" % lookup["property"], r"*%s*" % lookup["match"], wildcard=True) elif lookup["lookup"] == "starts": l |= Q(r"%s" % lookup["property"], r"%s*" % lookup["match"], wildcard=True) elif lookup["lookup"] == "ends": l |= Q(r"%s" % lookup["property"], r"*%s" % lookup["match"], wildcard=True) elif lookup["lookup"] == "exact": l |= Q(r"%s" % lookup["property"], r"%s" % lookup["match"]) q = q & (l) if include_properties: for node in idx.query(q): yield (node.id, node.properties) else: for node in idx.query(q): yield (node.id, None)
def test_lucene_query(): Human(name='sarah', age=3).save() Human(name='jim', age=4).save() Human(name='bob', age=5).save() Human(name='tim', age=2).save() names = [p.name for p in Human.index.search(Q('age', inrange=[3, 5]))] assert 'sarah' in names assert 'jim' in names assert 'bob' in names
def search(self, query=None, **kwargs): """ Load multiple nodes via index """ self._check_params(kwargs) if not query: query = reduce(lambda x, y: x & y, [Q(k, v) for k, v in kwargs.iteritems()]) return [ self.node_class.inflate(n) for n in self.__index__.query(str(query)) ]
def search(self, query=None, **kwargs): """Search nodes using an via index""" if not query: if not kwargs: msg = "No arguments provided.\nUsage: {0}.index.search(key=val)" msg += " or (lucene query): {0}.index.search('key:val').\n" msg += "To retrieve all nodes use the category node: {0}.category().instance.all()" raise ValueError(msg.format(self.node_class.__name__)) self._check_params(kwargs) query = functools.reduce(lambda x, y: x & y, [Q(k, v) for k, v in kwargs.items()]) return [self.node_class.inflate(n) for n in self._execute(str(query))]
def search(self, query=None, **kwargs): """Search nodes using an via index, if searching just for one properties, attemps to find if the property is on his own index""" index = self.__index__ if not query: if not kwargs: msg = "No arguments provided.\nUsage: {0}.index.search(key=val)" msg += " or (lucene query): {0}.index.search('key:val').\n" msg += "To retrieve all nodes use the category node: {0}.category().instance.all()" raise ValueError(msg.format(self.node_class.__name__)) self._check_params(kwargs) if len(kwargs.keys()) == 1: index = self._get_index(kwargs.keys()[0]) is_fulltext = self._get_index_type(kwargs.keys()[0]) == \ 'fulltext' if is_fulltext: qargs = {'wildcard': True} else: qargs = None if qargs: query = functools.reduce( lambda x, y: x & y, [Q(k, v, **qargs) for k, v in kwargs.items()]) else: query = functools.reduce( lambda x, y: x & y, [Q( k, v, ) for k, v in kwargs.items()]) elif not isinstance(query, Q): if len(query.split(':')) == 2: index = self._get_index(query.split(':')[0]) return [ self.node_class.inflate(n) for n in self._execute(index, str(query)) ]
def test_hashing(): q1 = Q('a') & Q('b') | Q('c') q2 = Q('a') & Q('b') | Q('c') q3 = q1 | Q('d') assert q1 == q2, "Queries aren't being properly evaluated for equality." assert q2 != q3, "Queries aren't being properly evaluated for inequality." d = {} try: d[q1] = 1 d[q2] = 2 except: raise AssertionError('There was an error using queries as dict keys.') assert d[q2] == 2, 'Got the wrong value back from the query dict!' q4 = Q('field', inrange=(1, 2)) q5 = Q('field', inrange=(1, 3)) assert q4 != q5 assert hash(q4) != hash(q5)
def test_query_index(self): n1 = self.gdb.nodes.create(name="John Doe", place="Texas") n2 = self.gdb.nodes.create(name="Michael Donald", place="Tijuana") index = self.gdb.nodes.indexes.create(name="do", type="fulltext") index["surnames"]["doe"] = n1 index["surnames"]["donald"] = n2 index['place']['Texas'] = n1 index['place']['Tijuana'] = n2 results = index.query("surnames", "do*") self.assertTrue(n1 in results and n2 in results) results = index.query("surnames:do*") self.assertTrue(n1 in results and n2 in results) results = index.query('surnames', Q('do*', wildcard=True)) self.assertTrue(n1 in results and n2 in results) results = index.query(Q('surnames', 'do*', wildcard=True)) self.assertTrue(n1 in results and n2 in results) results = index.query( Q('surnames', 'do*', wildcard=True) & Q('place', 'Tijuana')) self.assertTrue(n1 not in results and n2 in results) results = index.query(-Q('surnames', 'donald') | +Q('place', 'Texas')) self.assertTrue(n2 not in results and n1 in results)
def q_from_condition(condition): """ Build a Lucene query from a filtering condition. """ q = None field = condition.field attname = field.attname def escape_wilds(s): return str(s).replace('*','\*').replace('?','\?') if condition.operator is OPERATORS.EXACT: q = Q(attname, field.to_neo_index(condition.value)) elif condition.operator is OPERATORS.STARTSWITH: q = Q(attname, '%s*' % escape_wilds(condition.value), wildcard=True) elif condition.operator is OPERATORS.CONTAINS: q = Q(attname, '*%s*' % escape_wilds(condition.value), wildcard=True) elif condition.operator is OPERATORS.MEMBER: q = Q(attname, field.member_to_neo_index(condition.value)) elif condition.operator is OPERATORS.IN: q = reduce(or_, (Q(attname, field.to_neo_index(v)) for v in condition.value)) elif condition.operator is OPERATORS.MEMBER_IN: q = reduce(or_, (Q(attname, field.member_to_neo_index(v)) for v in condition.value)) #FIXME OBOE with field.MAX + exrange, not sure it's easy to fix though... elif condition.operator in (OPERATORS.GT, OPERATORS.GTE, OPERATORS.LT, OPERATORS.LTE, OPERATORS.RANGE): if not field.indexed_range: raise exceptions.FieldError( 'The {0} property is not configured for range ' 'indexing.'.format(field.attname)) fieldtype = field._property_type() if condition.operator in (OPERATORS.GT, OPERATORS.GTE): if not hasattr(field, 'MAX'): raise exceptions.FieldError( 'The {0} property is not configured for gt/gte ' 'queries.'.format(field.attname)) if condition.operator is OPERATORS.GT: q = Q(attname, exrange=(field.to_neo_index(condition.value), field.to_neo_index(fieldtype.MAX))) else: q = Q(attname, inrange=(field.to_neo_index(condition.value), field.to_neo_index(fieldtype.MAX))) elif condition.operator in (OPERATORS.LT, OPERATORS.LTE): if not hasattr(fieldtype, 'MIN'): raise exceptions.FieldError( 'The {0} property is not configured for lt/lte ' 'queries.'.format(field.attname)) if condition.operator is OPERATORS.LT: q = Q(attname, exrange=(field.to_neo_index(fieldtype.MIN), field.to_neo_index(condition.value))) else: q = Q(attname, inrange=(field.to_neo_index(fieldtype.MIN), field.to_neo_index(condition.value))) elif condition.operator is OPERATORS.RANGE: if len(condition.value) != 2: raise exceptions.ValidationError('Range queries need upper and' ' lower bounds.') q = Q(condition.field.attname, inrange=[condition.field.to_neo_index(v) for v in condition.value]) else: return None if condition.negate: q = ~q return q
def test_general(): a = 'a' b = 'b' c = 'c' d = 'd d' e = 'e' f = 'f' g = 1 h = 5 q1 = Q(a) | Q(b) assert str(q1) == '(' + a + ' OR ' + b + ')', str(q1) q2 = Q(c) & q1 assert str(q2) == '(' + c + ' AND (' + a + ' OR ' + b + '))' q3 = +Q(a) + Q(b) | Q(f, Q(c) & ~Q(Q(d) | Q(e))) assert str( q3 ) == '+' + a + ' +' + b + ' ' + f + ':((' + c + ' AND NOT ' + '("' + d + '" OR ' + e + ')))' q4 = Q(a, b) | Q(c, Q(d) & Q(e)) | Q(f, +Q(inrange=(g, h)) | Q(h)) assert str( q4 ) == a + ':(' + b + ') ' + c + ':(("' + d + '" AND ' + e + ')) ' + f + ':(+[' + str( g) + ' TO ' + str(h) + '] ' + str(h) + ')' try: q5 = Q(a, Q(b, Q(c, d) & Q(e)) | Q(f)) except: pass else: raise AssertionError("Shouldn't allow nested fields.")
def test_simple_phrase(): query_string = str(Q('abc 123')) assert query_string == '"abc 123"', query_string
def test_simple_term(): query_string = str(Q('a')) assert query_string == 'a', query_string
def test_wildcard(): eq_(str(Q('lol*', wildcard=True)), 'lol*') eq_(str(Q('field_with_*', 'some query')), 'field_with_*:("some query")') eq_(str(Q('field_with_*', 'some*query', wildcard=True)), 'field_with_*:(some*query)')