Skip to content

Commit

Permalink
Implement update op $min $max
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlatwe committed Jun 26, 2018
1 parent 3263700 commit b502a50
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 6 deletions.
4 changes: 3 additions & 1 deletion montydb/engine/core/weighted.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ def __le__(self, other):
class Weighted(tuple):
"""
"""

def __new__(cls, value):
return super(Weighted, cls).__new__(cls, gravity(value))

def __init__(self, value):
self.value = value


def gravity(value, weight_only=None):
"""
Expand Down
28 changes: 23 additions & 5 deletions montydb/engine/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from bson.decimal128 import Decimal128

from ..errors import WriteError
from .core import FieldSetValueError
from .core import FieldSetValueError, Weighted
from .queries import QueryFilter
from .helpers import is_numeric_type

Expand All @@ -19,7 +19,7 @@ def __init__(self, spec, array_filters=None):
# field update ops
"$inc": parse_inc,
"$min": parse_min,
"$max": None,
"$max": parse_max,
"$mul": None,
"$rename": None,
"$set": None,
Expand Down Expand Up @@ -155,14 +155,32 @@ def inc(old_val, inc_val):

def parse_min(field, value, array_filters):
def _min(fieldwalker):
raise NotImplementedError
def min(old_val, min_val):
old_val = Weighted(old_val)
min_val = Weighted(min_val)
return min_val.value if min_val < old_val else old_val.value

try:
return fieldwalker.go(field).set(value, min, array_filters)
except FieldSetValueError as err:
msg = err.message if hasattr(err, 'message') else str(err)
raise WriteError(msg, code=err.code)

return _min


def parse_max(field, value):
def parse_max(field, value, array_filters):
def _max(fieldwalker):
raise NotImplementedError
def max(old_val, max_val):
old_val = Weighted(old_val)
max_val = Weighted(max_val)
return max_val.value if max_val > old_val else old_val.value

try:
return fieldwalker.go(field).set(value, max, array_filters)
except FieldSetValueError as err:
msg = err.message if hasattr(err, 'message') else str(err)
raise WriteError(msg, code=err.code)

return _max

Expand Down
88 changes: 88 additions & 0 deletions tests/test_engine/test_update/test_update_max.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

from datetime import datetime
from bson.timestamp import Timestamp
from bson.max_key import MaxKey


def test_update_max_1(monty_update, mongo_update):
docs = [
{"a": 1}
]
spec = {"$max": {"a": 10}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": 10}


def test_update_max_2(monty_update, mongo_update):
docs = [
{"a": 1}
]
spec = {"$max": {"a": True}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": 1}


def test_update_max_3(monty_update, mongo_update):
docs = [
{"a": None}
]
spec = {"$max": {"a": True}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": True}


def test_update_max_4(monty_update, mongo_update):
docs = [
{"a": {"b": 5}}
]
spec = {"$max": {"a": MaxKey()}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": MaxKey()}


def test_update_max_5(monty_update, mongo_update):
docs = [
{"a": datetime(1998, 8, 22)}
]
spec = {"$max": {"a": datetime(1000, 8, 22)}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": datetime(1998, 8, 22)}


def test_update_max_6(monty_update, mongo_update):
docs = [
{"a": Timestamp(10, 5)}
]
spec = {"$max": {"a": Timestamp(10, 10)}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": Timestamp(10, 10)}
88 changes: 88 additions & 0 deletions tests/test_engine/test_update/test_update_min.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

from datetime import datetime
from bson.timestamp import Timestamp
from bson.max_key import MaxKey


def test_update_min_1(monty_update, mongo_update):
docs = [
{"a": 1}
]
spec = {"$min": {"a": 0}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": 0}


def test_update_min_2(monty_update, mongo_update):
docs = [
{"a": 1}
]
spec = {"$min": {"a": True}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": True}


def test_update_min_3(monty_update, mongo_update):
docs = [
{"a": {"b": 5}, "0": None}
]
spec = {"$min": {"a": {"b": 3}}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": {"b": 3}, "0": None}


def test_update_min_4(monty_update, mongo_update):
docs = [
{"a": {"b": 5}}
]
spec = {"$min": {"a": MaxKey()}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": {"b": 5}}


def test_update_min_5(monty_update, mongo_update):
docs = [
{"a": datetime(1998, 8, 22)}
]
spec = {"$min": {"a": datetime(1000, 8, 22)}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": datetime(1000, 8, 22)}


def test_update_min_6(monty_update, mongo_update):
docs = [
{"a": Timestamp(10, 5)}
]
spec = {"$min": {"a": Timestamp(10, 0)}}

monty_c = monty_update(docs, spec)
mongo_c = mongo_update(docs, spec)

assert next(mongo_c) == next(monty_c)
monty_c.rewind()
assert next(monty_c) == {"a": Timestamp(10, 0)}

0 comments on commit b502a50

Please sign in to comment.