Skip to content

Commit 106772f

Browse files
authored
feat: Use server side != for queries. (#950)
1 parent dab9edf commit 106772f

File tree

4 files changed

+21
-21
lines changed

4 files changed

+21
-21
lines changed

google/cloud/ndb/_datastore_query.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
"<=": query_pb2.PropertyFilter.Operator.LESS_THAN_OR_EQUAL,
5757
">": query_pb2.PropertyFilter.Operator.GREATER_THAN,
5858
">=": query_pb2.PropertyFilter.Operator.GREATER_THAN_OR_EQUAL,
59+
"!=": query_pb2.PropertyFilter.Operator.NOT_EQUAL,
60+
"IN": query_pb2.PropertyFilter.Operator.IN,
5961
}
6062

6163
_KEY_NOT_IN_CACHE = object()

google/cloud/ndb/query.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,6 @@ class FilterNode(Node):
604604
The constructor for this type may not always return a
605605
:class:`FilterNode`. For example:
606606
607-
* The filter ``name != value`` is converted into
608-
``(name > value) OR (name < value)`` (a :class:`DisjunctionNode`)
609607
* The filter ``name in (value1, ..., valueN)`` is converted into
610608
``(name = value1) OR ... OR (name = valueN)`` (also a
611609
:class:`DisjunctionNode`)
@@ -639,11 +637,6 @@ def __new__(cls, name, opsymbol, value):
639637
if isinstance(value, model.Key):
640638
value = value._key
641639

642-
if opsymbol == _NE_OP:
643-
node1 = FilterNode(name, _LT_OP, value)
644-
node2 = FilterNode(name, _GT_OP, value)
645-
return DisjunctionNode(node1, node2)
646-
647640
if opsymbol == _IN_OP:
648641
if not isinstance(value, (list, tuple, set, frozenset)):
649642
raise TypeError(
@@ -704,17 +697,17 @@ def _to_filter(self, post=False):
704697
representation of the filter.
705698
706699
Raises:
707-
NotImplementedError: If the ``opsymbol`` is ``!=`` or ``in``, since
700+
NotImplementedError: If the ``opsymbol`` is ``in``, since
708701
they should correspond to a composite filter. This should
709702
never occur since the constructor will create ``OR`` nodes for
710-
``!=`` and ``in``
703+
``in``
711704
"""
712705
# Avoid circular import in Python 2.7
713706
from google.cloud.ndb import _datastore_query
714707

715708
if post:
716709
return None
717-
if self._opsymbol in (_NE_OP, _IN_OP):
710+
if self._opsymbol in (_IN_OP):
718711
raise NotImplementedError(
719712
"Inequality filters are not single filter "
720713
"expressions and therefore cannot be converted "

tests/unit/test_model.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,12 @@ def test___eq__():
479479
def test___ne__():
480480
prop = model.Property("name", indexed=True)
481481
value = 7.0
482-
expected = query_module.DisjunctionNode(
483-
query_module.FilterNode("name", "<", value),
484-
query_module.FilterNode("name", ">", value),
485-
)
482+
expected = query_module.FilterNode("name", "!=", value)
486483

487-
or_node_left = prop != value
488-
assert or_node_left == expected
489-
or_node_right = value != prop
490-
assert or_node_right == expected
484+
ne_node_left = prop != value
485+
assert ne_node_left == expected
486+
ne_node_right = value != prop
487+
assert ne_node_right == expected
491488

492489
@staticmethod
493490
def test___lt__():

tests/unit/test_query.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,11 +656,14 @@ def test_constructor_in_invalid_container():
656656

657657
@staticmethod
658658
def test_constructor_ne():
659-
or_node = query_module.FilterNode("a", "!=", 2.5)
659+
ne_node = query_module.FilterNode("a", "!=", 2.5)
660660

661661
filter_node1 = query_module.FilterNode("a", "<", 2.5)
662662
filter_node2 = query_module.FilterNode("a", ">", 2.5)
663-
assert or_node == query_module.DisjunctionNode(filter_node1, filter_node2)
663+
assert ne_node != query_module.DisjunctionNode(filter_node1, filter_node2)
664+
assert ne_node._value == 2.5
665+
assert ne_node._opsymbol == "!="
666+
assert ne_node._name == "a"
664667

665668
@staticmethod
666669
def test_pickling():
@@ -693,10 +696,15 @@ def test__to_filter_post():
693696
filter_node = query_module.FilterNode("speed", ">=", 88)
694697
assert filter_node._to_filter(post=True) is None
695698

699+
@staticmethod
700+
def test__to_ne_filter_op():
701+
filter_node = query_module.FilterNode("speed", "!=", 88)
702+
assert filter_node._to_filter(post=True) is None
703+
696704
@staticmethod
697705
def test__to_filter_bad_op():
698706
filter_node = query_module.FilterNode("speed", ">=", 88)
699-
filter_node._opsymbol = "!="
707+
filter_node._opsymbol = "in"
700708
with pytest.raises(NotImplementedError):
701709
filter_node._to_filter()
702710

0 commit comments

Comments
 (0)