|
|
|
|
@@ -3,12 +3,14 @@
|
|
|
|
|
import datetime
|
|
|
|
|
import unittest
|
|
|
|
|
import uuid
|
|
|
|
|
from decimal import Decimal
|
|
|
|
|
|
|
|
|
|
from bson import DBRef, ObjectId
|
|
|
|
|
from nose.plugins.skip import SkipTest
|
|
|
|
|
import pymongo
|
|
|
|
|
from pymongo.errors import ConfigurationError
|
|
|
|
|
from pymongo.read_preferences import ReadPreference
|
|
|
|
|
from pymongo.results import UpdateResult
|
|
|
|
|
import six
|
|
|
|
|
|
|
|
|
|
from mongoengine import *
|
|
|
|
|
@@ -57,11 +59,10 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
def test_initialisation(self):
|
|
|
|
|
"""Ensure that a QuerySet is correctly initialised by QuerySetManager.
|
|
|
|
|
"""
|
|
|
|
|
self.assertTrue(isinstance(self.Person.objects, QuerySet))
|
|
|
|
|
self.assertIsInstance(self.Person.objects, QuerySet)
|
|
|
|
|
self.assertEqual(self.Person.objects._collection.name,
|
|
|
|
|
self.Person._get_collection_name())
|
|
|
|
|
self.assertTrue(isinstance(self.Person.objects._collection,
|
|
|
|
|
pymongo.collection.Collection))
|
|
|
|
|
self.assertIsInstance(self.Person.objects._collection, pymongo.collection.Collection)
|
|
|
|
|
|
|
|
|
|
def test_cannot_perform_joins_references(self):
|
|
|
|
|
|
|
|
|
|
@@ -87,8 +88,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(people.count(), 2)
|
|
|
|
|
results = list(people)
|
|
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(results[0], self.Person))
|
|
|
|
|
self.assertTrue(isinstance(results[0].id, (ObjectId, str, unicode)))
|
|
|
|
|
self.assertIsInstance(results[0], self.Person)
|
|
|
|
|
self.assertIsInstance(results[0].id, (ObjectId, str, unicode))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(results[0], user_a)
|
|
|
|
|
self.assertEqual(results[0].name, 'User A')
|
|
|
|
|
@@ -228,7 +229,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
# Retrieve the first person from the database
|
|
|
|
|
person = self.Person.objects.first()
|
|
|
|
|
self.assertTrue(isinstance(person, self.Person))
|
|
|
|
|
self.assertIsInstance(person, self.Person)
|
|
|
|
|
self.assertEqual(person.name, "User A")
|
|
|
|
|
self.assertEqual(person.age, 20)
|
|
|
|
|
|
|
|
|
|
@@ -594,6 +595,20 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
Scores.objects(id=scores.id).update(max__high_score=500)
|
|
|
|
|
self.assertEqual(Scores.objects.get(id=scores.id).high_score, 1000)
|
|
|
|
|
|
|
|
|
|
@needs_mongodb_v26
|
|
|
|
|
def test_update_multiple(self):
|
|
|
|
|
class Product(Document):
|
|
|
|
|
item = StringField()
|
|
|
|
|
price = FloatField()
|
|
|
|
|
|
|
|
|
|
product = Product.objects.create(item='ABC', price=10.99)
|
|
|
|
|
product = Product.objects.create(item='ABC', price=10.99)
|
|
|
|
|
Product.objects(id=product.id).update(mul__price=1.25)
|
|
|
|
|
self.assertEqual(Product.objects.get(id=product.id).price, 13.7375)
|
|
|
|
|
unknown_product = Product.objects.create(item='Unknown')
|
|
|
|
|
Product.objects(id=unknown_product.id).update(mul__price=100)
|
|
|
|
|
self.assertEqual(Product.objects.get(id=unknown_product.id).price, 0)
|
|
|
|
|
|
|
|
|
|
def test_updates_can_have_match_operators(self):
|
|
|
|
|
|
|
|
|
|
class Comment(EmbeddedDocument):
|
|
|
|
|
@@ -661,14 +676,14 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
result = self.Person(name="Bob", age=25).update(
|
|
|
|
|
upsert=True, full_result=True)
|
|
|
|
|
self.assertTrue(isinstance(result, dict))
|
|
|
|
|
self.assertTrue("upserted" in result)
|
|
|
|
|
self.assertFalse(result["updatedExisting"])
|
|
|
|
|
self.assertIsInstance(result, UpdateResult)
|
|
|
|
|
self.assertIn("upserted", result.raw_result)
|
|
|
|
|
self.assertFalse(result.raw_result["updatedExisting"])
|
|
|
|
|
|
|
|
|
|
bob = self.Person.objects.first()
|
|
|
|
|
result = bob.update(set__age=30, full_result=True)
|
|
|
|
|
self.assertTrue(isinstance(result, dict))
|
|
|
|
|
self.assertTrue(result["updatedExisting"])
|
|
|
|
|
self.assertIsInstance(result, UpdateResult)
|
|
|
|
|
self.assertTrue(result.raw_result["updatedExisting"])
|
|
|
|
|
|
|
|
|
|
self.Person(name="Bob", age=20).save()
|
|
|
|
|
result = self.Person.objects(name="Bob").update(
|
|
|
|
|
@@ -835,11 +850,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
blogs.append(Blog(title="post %s" % i, posts=[post1, post2]))
|
|
|
|
|
|
|
|
|
|
Blog.objects.insert(blogs, load_bulk=False)
|
|
|
|
|
if mongodb_version < (2, 6):
|
|
|
|
|
self.assertEqual(q, 1)
|
|
|
|
|
else:
|
|
|
|
|
# profiling logs each doc now in the bulk op
|
|
|
|
|
self.assertEqual(q, 99)
|
|
|
|
|
# profiling logs each doc now in the bulk op
|
|
|
|
|
self.assertEqual(q, 99)
|
|
|
|
|
|
|
|
|
|
Blog.drop_collection()
|
|
|
|
|
Blog.ensure_indexes()
|
|
|
|
|
@@ -848,11 +860,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(q, 0)
|
|
|
|
|
|
|
|
|
|
Blog.objects.insert(blogs)
|
|
|
|
|
if mongodb_version < (2, 6):
|
|
|
|
|
self.assertEqual(q, 2) # 1 for insert, and 1 for in bulk fetch
|
|
|
|
|
else:
|
|
|
|
|
# 99 for insert, and 1 for in bulk fetch
|
|
|
|
|
self.assertEqual(q, 100)
|
|
|
|
|
self.assertEqual(q, 100) # 99 for insert 1 for fetch
|
|
|
|
|
|
|
|
|
|
Blog.drop_collection()
|
|
|
|
|
|
|
|
|
|
@@ -917,10 +925,6 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
self.assertEqual(Blog.objects.count(), 2)
|
|
|
|
|
|
|
|
|
|
Blog.objects.insert([blog2, blog3],
|
|
|
|
|
write_concern={"w": 0, 'continue_on_error': True})
|
|
|
|
|
self.assertEqual(Blog.objects.count(), 3)
|
|
|
|
|
|
|
|
|
|
def test_get_changed_fields_query_count(self):
|
|
|
|
|
"""Make sure we don't perform unnecessary db operations when
|
|
|
|
|
none of document's fields were updated.
|
|
|
|
|
@@ -994,7 +998,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
# Retrieve the first person from the database
|
|
|
|
|
person = self.Person.objects.slave_okay(True).first()
|
|
|
|
|
self.assertTrue(isinstance(person, self.Person))
|
|
|
|
|
self.assertIsInstance(person, self.Person)
|
|
|
|
|
self.assertEqual(person.name, "User A")
|
|
|
|
|
self.assertEqual(person.age, 20)
|
|
|
|
|
|
|
|
|
|
@@ -1061,10 +1065,10 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(docs.count(), 1000)
|
|
|
|
|
|
|
|
|
|
docs_string = "%s" % docs
|
|
|
|
|
self.assertTrue("Doc: 0" in docs_string)
|
|
|
|
|
self.assertIn("Doc: 0", docs_string)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(docs.count(), 1000)
|
|
|
|
|
self.assertTrue('(remaining elements truncated)' in "%s" % docs)
|
|
|
|
|
self.assertIn('(remaining elements truncated)', "%s" % docs)
|
|
|
|
|
|
|
|
|
|
# Limit and skip
|
|
|
|
|
docs = docs[1:4]
|
|
|
|
|
@@ -1203,6 +1207,14 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
Blog.drop_collection()
|
|
|
|
|
|
|
|
|
|
def test_filter_chaining_with_regex(self):
|
|
|
|
|
person = self.Person(name='Guido van Rossum')
|
|
|
|
|
person.save()
|
|
|
|
|
|
|
|
|
|
people = self.Person.objects
|
|
|
|
|
people = people.filter(name__startswith='Gui').filter(name__not__endswith='tum')
|
|
|
|
|
self.assertEqual(people.count(), 1)
|
|
|
|
|
|
|
|
|
|
def assertSequence(self, qs, expected):
|
|
|
|
|
qs = list(qs)
|
|
|
|
|
expected = list(expected)
|
|
|
|
|
@@ -1273,7 +1285,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
with db_ops_tracker() as q:
|
|
|
|
|
BlogPost.objects.filter(title='whatever').order_by().first()
|
|
|
|
|
self.assertEqual(len(q.get_ops()), 1)
|
|
|
|
|
self.assertFalse('$orderby' in q.get_ops()[0]['query'])
|
|
|
|
|
self.assertNotIn('$orderby', q.get_ops()[0]['query'])
|
|
|
|
|
|
|
|
|
|
# calling an explicit order_by should use a specified sort
|
|
|
|
|
with db_ops_tracker() as q:
|
|
|
|
|
@@ -1289,7 +1301,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
qs = BlogPost.objects.filter(title='whatever').order_by('published_date')
|
|
|
|
|
qs.order_by().first()
|
|
|
|
|
self.assertEqual(len(q.get_ops()), 1)
|
|
|
|
|
self.assertFalse('$orderby' in q.get_ops()[0]['query'])
|
|
|
|
|
self.assertNotIn('$orderby', q.get_ops()[0]['query'])
|
|
|
|
|
|
|
|
|
|
def test_no_ordering_for_get(self):
|
|
|
|
|
""" Ensure that Doc.objects.get doesn't use any ordering.
|
|
|
|
|
@@ -1308,13 +1320,13 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
with db_ops_tracker() as q:
|
|
|
|
|
BlogPost.objects.get(title='whatever')
|
|
|
|
|
self.assertEqual(len(q.get_ops()), 1)
|
|
|
|
|
self.assertFalse('$orderby' in q.get_ops()[0]['query'])
|
|
|
|
|
self.assertNotIn('$orderby', q.get_ops()[0]['query'])
|
|
|
|
|
|
|
|
|
|
# Ordering should be ignored for .get even if we set it explicitly
|
|
|
|
|
with db_ops_tracker() as q:
|
|
|
|
|
BlogPost.objects.order_by('-title').get(title='whatever')
|
|
|
|
|
self.assertEqual(len(q.get_ops()), 1)
|
|
|
|
|
self.assertFalse('$orderby' in q.get_ops()[0]['query'])
|
|
|
|
|
self.assertNotIn('$orderby', q.get_ops()[0]['query'])
|
|
|
|
|
|
|
|
|
|
def test_find_embedded(self):
|
|
|
|
|
"""Ensure that an embedded document is properly returned from
|
|
|
|
|
@@ -1336,15 +1348,15 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
result = BlogPost.objects.first()
|
|
|
|
|
self.assertTrue(isinstance(result.author, User))
|
|
|
|
|
self.assertIsInstance(result.author, User)
|
|
|
|
|
self.assertEqual(result.author.name, 'Test User')
|
|
|
|
|
|
|
|
|
|
result = BlogPost.objects.get(author__name=user.name)
|
|
|
|
|
self.assertTrue(isinstance(result.author, User))
|
|
|
|
|
self.assertIsInstance(result.author, User)
|
|
|
|
|
self.assertEqual(result.author.name, 'Test User')
|
|
|
|
|
|
|
|
|
|
result = BlogPost.objects.get(author={'name': user.name})
|
|
|
|
|
self.assertTrue(isinstance(result.author, User))
|
|
|
|
|
self.assertIsInstance(result.author, User)
|
|
|
|
|
self.assertEqual(result.author.name, 'Test User')
|
|
|
|
|
|
|
|
|
|
# Fails, since the string is not a type that is able to represent the
|
|
|
|
|
@@ -1462,7 +1474,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
code_chunks = ['doc["cmnts"];', 'doc["doc-name"],',
|
|
|
|
|
'doc["cmnts"][i]["body"]']
|
|
|
|
|
for chunk in code_chunks:
|
|
|
|
|
self.assertTrue(chunk in sub_code)
|
|
|
|
|
self.assertIn(chunk, sub_code)
|
|
|
|
|
|
|
|
|
|
results = BlogPost.objects.exec_js(code)
|
|
|
|
|
expected_results = [
|
|
|
|
|
@@ -1852,21 +1864,16 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
1, BlogPost.objects(author__in=["%s" % me.pk]).count())
|
|
|
|
|
|
|
|
|
|
def test_update(self):
|
|
|
|
|
"""Ensure that atomic updates work properly.
|
|
|
|
|
"""
|
|
|
|
|
def test_update_intfield_operator(self):
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
name = StringField()
|
|
|
|
|
title = StringField()
|
|
|
|
|
hits = IntField()
|
|
|
|
|
tags = ListField(StringField())
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(name="Test Post", hits=5, tags=['test'])
|
|
|
|
|
post = BlogPost(hits=5)
|
|
|
|
|
post.save()
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update(set__hits=10)
|
|
|
|
|
BlogPost.objects.update_one(set__hits=10)
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.hits, 10)
|
|
|
|
|
|
|
|
|
|
@@ -1883,13 +1890,63 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.hits, 11)
|
|
|
|
|
|
|
|
|
|
def test_update_decimalfield_operator(self):
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
review = DecimalField()
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(review=3.5)
|
|
|
|
|
post.save()
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update_one(inc__review=0.1) # test with floats
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(float(post.review), 3.6)
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update_one(dec__review=0.1)
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(float(post.review), 3.5)
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update_one(inc__review=Decimal(0.12)) # test with Decimal
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(float(post.review), 3.62)
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update_one(dec__review=Decimal(0.12))
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(float(post.review), 3.5)
|
|
|
|
|
|
|
|
|
|
def test_update_decimalfield_operator_not_working_with_force_string(self):
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
review = DecimalField(force_string=True)
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(review=3.5)
|
|
|
|
|
post.save()
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(OperationError):
|
|
|
|
|
BlogPost.objects.update_one(inc__review=0.1) # test with floats
|
|
|
|
|
|
|
|
|
|
def test_update_listfield_operator(self):
|
|
|
|
|
"""Ensure that atomic updates work properly.
|
|
|
|
|
"""
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
tags = ListField(StringField())
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(tags=['test'])
|
|
|
|
|
post.save()
|
|
|
|
|
|
|
|
|
|
# ListField operator
|
|
|
|
|
BlogPost.objects.update(push__tags='mongo')
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertTrue('mongo' in post.tags)
|
|
|
|
|
self.assertIn('mongo', post.tags)
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.update_one(push_all__tags=['db', 'nosql'])
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertTrue('db' in post.tags and 'nosql' in post.tags)
|
|
|
|
|
self.assertIn('db', post.tags)
|
|
|
|
|
self.assertIn('nosql', post.tags)
|
|
|
|
|
|
|
|
|
|
tags = post.tags[:-1]
|
|
|
|
|
BlogPost.objects.update(pop__tags=1)
|
|
|
|
|
@@ -1901,13 +1958,23 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.tags.count('unique'), 1)
|
|
|
|
|
|
|
|
|
|
self.assertNotEqual(post.hits, None)
|
|
|
|
|
BlogPost.objects.update_one(unset__hits=1)
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.hits, None)
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
def test_update_unset(self):
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
title = StringField()
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(title='garbage').save()
|
|
|
|
|
|
|
|
|
|
self.assertNotEqual(post.title, None)
|
|
|
|
|
BlogPost.objects.update_one(unset__title=1)
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.title, None)
|
|
|
|
|
pymongo_doc = BlogPost.objects.as_pymongo().first()
|
|
|
|
|
self.assertNotIn('title', pymongo_doc)
|
|
|
|
|
|
|
|
|
|
@needs_mongodb_v26
|
|
|
|
|
def test_update_push_with_position(self):
|
|
|
|
|
"""Ensure that the 'push' update with position works properly.
|
|
|
|
|
@@ -1934,6 +2001,21 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.tags, ['scala', 'mongodb', 'python', 'java'])
|
|
|
|
|
|
|
|
|
|
def test_update_push_list_of_list(self):
|
|
|
|
|
"""Ensure that the 'push' update operation works in the list of list
|
|
|
|
|
"""
|
|
|
|
|
class BlogPost(Document):
|
|
|
|
|
slug = StringField()
|
|
|
|
|
tags = ListField()
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
post = BlogPost(slug="test").save()
|
|
|
|
|
|
|
|
|
|
BlogPost.objects.filter(slug="test").update(push__tags=["value1", 123])
|
|
|
|
|
post.reload()
|
|
|
|
|
self.assertEqual(post.tags, [["value1", 123]])
|
|
|
|
|
|
|
|
|
|
def test_update_push_and_pull_add_to_set(self):
|
|
|
|
|
"""Ensure that the 'pull' update operation works correctly.
|
|
|
|
|
"""
|
|
|
|
|
@@ -2076,6 +2158,23 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
Site.objects(id=s.id).update_one(
|
|
|
|
|
pull_all__collaborators__helpful__user=['Ross'])
|
|
|
|
|
|
|
|
|
|
def test_pull_in_genericembedded_field(self):
|
|
|
|
|
|
|
|
|
|
class Foo(EmbeddedDocument):
|
|
|
|
|
name = StringField()
|
|
|
|
|
|
|
|
|
|
class Bar(Document):
|
|
|
|
|
foos = ListField(GenericEmbeddedDocumentField(
|
|
|
|
|
choices=[Foo, ]))
|
|
|
|
|
|
|
|
|
|
Bar.drop_collection()
|
|
|
|
|
|
|
|
|
|
foo = Foo(name="bar")
|
|
|
|
|
bar = Bar(foos=[foo]).save()
|
|
|
|
|
Bar.objects(id=bar.id).update(pull__foos=foo)
|
|
|
|
|
bar.reload()
|
|
|
|
|
self.assertEqual(len(bar.foos), 0)
|
|
|
|
|
|
|
|
|
|
def test_update_one_pop_generic_reference(self):
|
|
|
|
|
|
|
|
|
|
class BlogTag(Document):
|
|
|
|
|
@@ -2169,6 +2268,24 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(message.authors[1].name, "Ross")
|
|
|
|
|
self.assertEqual(message.authors[2].name, "Adam")
|
|
|
|
|
|
|
|
|
|
def test_set_generic_embedded_documents(self):
|
|
|
|
|
|
|
|
|
|
class Bar(EmbeddedDocument):
|
|
|
|
|
name = StringField()
|
|
|
|
|
|
|
|
|
|
class User(Document):
|
|
|
|
|
username = StringField()
|
|
|
|
|
bar = GenericEmbeddedDocumentField(choices=[Bar,])
|
|
|
|
|
|
|
|
|
|
User.drop_collection()
|
|
|
|
|
|
|
|
|
|
User(username='abc').save()
|
|
|
|
|
User.objects(username='abc').update(
|
|
|
|
|
set__bar=Bar(name='test'), upsert=True)
|
|
|
|
|
|
|
|
|
|
user = User.objects(username='abc').first()
|
|
|
|
|
self.assertEqual(user.bar.name, "test")
|
|
|
|
|
|
|
|
|
|
def test_reload_embedded_docs_instance(self):
|
|
|
|
|
|
|
|
|
|
class SubDoc(EmbeddedDocument):
|
|
|
|
|
@@ -2338,14 +2455,19 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
age = IntField()
|
|
|
|
|
|
|
|
|
|
with db_ops_tracker() as q:
|
|
|
|
|
adult = (User.objects.filter(age__gte=18)
|
|
|
|
|
adult1 = (User.objects.filter(age__gte=18)
|
|
|
|
|
.comment('looking for an adult')
|
|
|
|
|
.first())
|
|
|
|
|
|
|
|
|
|
adult2 = (User.objects.comment('looking for an adult')
|
|
|
|
|
.filter(age__gte=18)
|
|
|
|
|
.first())
|
|
|
|
|
|
|
|
|
|
ops = q.get_ops()
|
|
|
|
|
self.assertEqual(len(ops), 1)
|
|
|
|
|
op = ops[0]
|
|
|
|
|
self.assertEqual(op['query']['$query'], {'age': {'$gte': 18}})
|
|
|
|
|
self.assertEqual(op['query']['$comment'], 'looking for an adult')
|
|
|
|
|
self.assertEqual(len(ops), 2)
|
|
|
|
|
for op in ops:
|
|
|
|
|
self.assertEqual(op['query']['$query'], {'age': {'$gte': 18}})
|
|
|
|
|
self.assertEqual(op['query']['$comment'], 'looking for an adult')
|
|
|
|
|
|
|
|
|
|
def test_map_reduce(self):
|
|
|
|
|
"""Ensure map/reduce is both mapping and reducing.
|
|
|
|
|
@@ -3157,8 +3279,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
News.drop_collection()
|
|
|
|
|
info = News.objects._collection.index_information()
|
|
|
|
|
self.assertTrue('title_text_content_text' in info)
|
|
|
|
|
self.assertTrue('textIndexVersion' in info['title_text_content_text'])
|
|
|
|
|
self.assertIn('title_text_content_text', info)
|
|
|
|
|
self.assertIn('textIndexVersion', info['title_text_content_text'])
|
|
|
|
|
|
|
|
|
|
News(title="Neymar quebrou a vertebra",
|
|
|
|
|
content="O Brasil sofre com a perda de Neymar").save()
|
|
|
|
|
@@ -3192,15 +3314,15 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
'$search': 'dilma', '$language': 'pt'},
|
|
|
|
|
'is_active': False})
|
|
|
|
|
|
|
|
|
|
self.assertEqual(new.is_active, False)
|
|
|
|
|
self.assertTrue('dilma' in new.content)
|
|
|
|
|
self.assertTrue('planejamento' in new.title)
|
|
|
|
|
self.assertFalse(new.is_active)
|
|
|
|
|
self.assertIn('dilma', new.content)
|
|
|
|
|
self.assertIn('planejamento', new.title)
|
|
|
|
|
|
|
|
|
|
query = News.objects.search_text("candidata")
|
|
|
|
|
self.assertEqual(query._search_text, "candidata")
|
|
|
|
|
new = query.first()
|
|
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(new.get_text_score(), float))
|
|
|
|
|
self.assertIsInstance(new.get_text_score(), float)
|
|
|
|
|
|
|
|
|
|
# count
|
|
|
|
|
query = News.objects.search_text('brasil').order_by('$text_score')
|
|
|
|
|
@@ -3495,39 +3617,12 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
Group.objects(id=group.id).update(set__members=[user1, user2])
|
|
|
|
|
group.reload()
|
|
|
|
|
|
|
|
|
|
self.assertTrue(len(group.members) == 2)
|
|
|
|
|
self.assertEqual(len(group.members), 2)
|
|
|
|
|
self.assertEqual(group.members[0].name, user1.name)
|
|
|
|
|
self.assertEqual(group.members[1].name, user2.name)
|
|
|
|
|
|
|
|
|
|
Group.drop_collection()
|
|
|
|
|
|
|
|
|
|
def test_dict_with_custom_baseclass(self):
|
|
|
|
|
"""Ensure DictField working with custom base clases.
|
|
|
|
|
"""
|
|
|
|
|
class Test(Document):
|
|
|
|
|
testdict = DictField()
|
|
|
|
|
|
|
|
|
|
Test.drop_collection()
|
|
|
|
|
|
|
|
|
|
t = Test(testdict={'f': 'Value'})
|
|
|
|
|
t.save()
|
|
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
Test.objects(testdict__f__startswith='Val').count(), 1)
|
|
|
|
|
self.assertEqual(Test.objects(testdict__f='Value').count(), 1)
|
|
|
|
|
Test.drop_collection()
|
|
|
|
|
|
|
|
|
|
class Test(Document):
|
|
|
|
|
testdict = DictField(basecls=StringField)
|
|
|
|
|
|
|
|
|
|
t = Test(testdict={'f': 'Value'})
|
|
|
|
|
t.save()
|
|
|
|
|
|
|
|
|
|
self.assertEqual(Test.objects(testdict__f='Value').count(), 1)
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
Test.objects(testdict__f__startswith='Val').count(), 1)
|
|
|
|
|
Test.drop_collection()
|
|
|
|
|
|
|
|
|
|
def test_bulk(self):
|
|
|
|
|
"""Ensure bulk querying by object id returns a proper dict.
|
|
|
|
|
"""
|
|
|
|
|
@@ -3553,13 +3648,13 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
self.assertEqual(len(objects), 3)
|
|
|
|
|
|
|
|
|
|
self.assertTrue(post_1.id in objects)
|
|
|
|
|
self.assertTrue(post_2.id in objects)
|
|
|
|
|
self.assertTrue(post_5.id in objects)
|
|
|
|
|
self.assertIn(post_1.id, objects)
|
|
|
|
|
self.assertIn(post_2.id, objects)
|
|
|
|
|
self.assertIn(post_5.id, objects)
|
|
|
|
|
|
|
|
|
|
self.assertTrue(objects[post_1.id].title == post_1.title)
|
|
|
|
|
self.assertTrue(objects[post_2.id].title == post_2.title)
|
|
|
|
|
self.assertTrue(objects[post_5.id].title == post_5.title)
|
|
|
|
|
self.assertEqual(objects[post_1.id].title, post_1.title)
|
|
|
|
|
self.assertEqual(objects[post_2.id].title, post_2.title)
|
|
|
|
|
self.assertEqual(objects[post_5.id].title, post_5.title)
|
|
|
|
|
|
|
|
|
|
BlogPost.drop_collection()
|
|
|
|
|
|
|
|
|
|
@@ -3579,7 +3674,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
Post.drop_collection()
|
|
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(Post.objects, CustomQuerySet))
|
|
|
|
|
self.assertIsInstance(Post.objects, CustomQuerySet)
|
|
|
|
|
self.assertFalse(Post.objects.not_empty())
|
|
|
|
|
|
|
|
|
|
Post().save()
|
|
|
|
|
@@ -3604,7 +3699,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
Post.drop_collection()
|
|
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(Post.objects, CustomQuerySet))
|
|
|
|
|
self.assertIsInstance(Post.objects, CustomQuerySet)
|
|
|
|
|
self.assertFalse(Post.objects.not_empty())
|
|
|
|
|
|
|
|
|
|
Post().save()
|
|
|
|
|
@@ -3651,7 +3746,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
Post.drop_collection()
|
|
|
|
|
self.assertTrue(isinstance(Post.objects, CustomQuerySet))
|
|
|
|
|
self.assertIsInstance(Post.objects, CustomQuerySet)
|
|
|
|
|
self.assertFalse(Post.objects.not_empty())
|
|
|
|
|
|
|
|
|
|
Post().save()
|
|
|
|
|
@@ -3679,7 +3774,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
Post.drop_collection()
|
|
|
|
|
self.assertTrue(isinstance(Post.objects, CustomQuerySet))
|
|
|
|
|
self.assertIsInstance(Post.objects, CustomQuerySet)
|
|
|
|
|
self.assertFalse(Post.objects.not_empty())
|
|
|
|
|
|
|
|
|
|
Post().save()
|
|
|
|
|
@@ -3770,17 +3865,17 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
test = Number.objects
|
|
|
|
|
test2 = test.clone()
|
|
|
|
|
self.assertFalse(test == test2)
|
|
|
|
|
self.assertNotEqual(test, test2)
|
|
|
|
|
self.assertEqual(test.count(), test2.count())
|
|
|
|
|
|
|
|
|
|
test = test.filter(n__gt=11)
|
|
|
|
|
test2 = test.clone()
|
|
|
|
|
self.assertFalse(test == test2)
|
|
|
|
|
self.assertNotEqual(test, test2)
|
|
|
|
|
self.assertEqual(test.count(), test2.count())
|
|
|
|
|
|
|
|
|
|
test = test.limit(10)
|
|
|
|
|
test2 = test.clone()
|
|
|
|
|
self.assertFalse(test == test2)
|
|
|
|
|
self.assertNotEqual(test, test2)
|
|
|
|
|
self.assertEqual(test.count(), test2.count())
|
|
|
|
|
|
|
|
|
|
Number.drop_collection()
|
|
|
|
|
@@ -3870,7 +3965,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
value.get('unique', False),
|
|
|
|
|
value.get('sparse', False))
|
|
|
|
|
for key, value in info.iteritems()]
|
|
|
|
|
self.assertTrue(([('_cls', 1), ('message', 1)], False, False) in info)
|
|
|
|
|
self.assertIn(([('_cls', 1), ('message', 1)], False, False), info)
|
|
|
|
|
|
|
|
|
|
def test_where(self):
|
|
|
|
|
"""Ensure that where clauses work.
|
|
|
|
|
@@ -3894,13 +3989,13 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
'this["fielda"] >= this["fieldb"]', query._where_clause)
|
|
|
|
|
results = list(query)
|
|
|
|
|
self.assertEqual(2, len(results))
|
|
|
|
|
self.assertTrue(a in results)
|
|
|
|
|
self.assertTrue(c in results)
|
|
|
|
|
self.assertIn(a, results)
|
|
|
|
|
self.assertIn(c, results)
|
|
|
|
|
|
|
|
|
|
query = IntPair.objects.where('this[~fielda] == this[~fieldb]')
|
|
|
|
|
results = list(query)
|
|
|
|
|
self.assertEqual(1, len(results))
|
|
|
|
|
self.assertTrue(a in results)
|
|
|
|
|
self.assertIn(a, results)
|
|
|
|
|
|
|
|
|
|
query = IntPair.objects.where(
|
|
|
|
|
'function() { return this[~fielda] >= this[~fieldb] }')
|
|
|
|
|
@@ -3908,8 +4003,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
'function() { return this["fielda"] >= this["fieldb"] }', query._where_clause)
|
|
|
|
|
results = list(query)
|
|
|
|
|
self.assertEqual(2, len(results))
|
|
|
|
|
self.assertTrue(a in results)
|
|
|
|
|
self.assertTrue(c in results)
|
|
|
|
|
self.assertIn(a, results)
|
|
|
|
|
self.assertIn(c, results)
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(TypeError):
|
|
|
|
|
list(IntPair.objects.where(fielda__gte=3))
|
|
|
|
|
@@ -4291,7 +4386,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
Test.drop_collection()
|
|
|
|
|
Test.objects(test='foo').update_one(upsert=True, set__test='foo')
|
|
|
|
|
self.assertFalse('_cls' in Test._collection.find_one())
|
|
|
|
|
self.assertNotIn('_cls', Test._collection.find_one())
|
|
|
|
|
|
|
|
|
|
class Test(Document):
|
|
|
|
|
meta = {'allow_inheritance': True}
|
|
|
|
|
@@ -4300,7 +4395,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
Test.drop_collection()
|
|
|
|
|
|
|
|
|
|
Test.objects(test='foo').update_one(upsert=True, set__test='foo')
|
|
|
|
|
self.assertTrue('_cls' in Test._collection.find_one())
|
|
|
|
|
self.assertIn('_cls', Test._collection.find_one())
|
|
|
|
|
|
|
|
|
|
def test_update_upsert_looks_like_a_digit(self):
|
|
|
|
|
class MyDoc(DynamicDocument):
|
|
|
|
|
@@ -4384,6 +4479,25 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
self.assertEqual(bars._cursor._Cursor__read_preference,
|
|
|
|
|
ReadPreference.SECONDARY_PREFERRED)
|
|
|
|
|
|
|
|
|
|
@needs_mongodb_v26
|
|
|
|
|
def test_read_preference_aggregation_framework(self):
|
|
|
|
|
class Bar(Document):
|
|
|
|
|
txt = StringField()
|
|
|
|
|
|
|
|
|
|
meta = {
|
|
|
|
|
'indexes': ['txt']
|
|
|
|
|
}
|
|
|
|
|
# Aggregates with read_preference
|
|
|
|
|
bars = Bar.objects \
|
|
|
|
|
.read_preference(ReadPreference.SECONDARY_PREFERRED) \
|
|
|
|
|
.aggregate()
|
|
|
|
|
if IS_PYMONGO_3:
|
|
|
|
|
self.assertEqual(bars._CommandCursor__collection.read_preference,
|
|
|
|
|
ReadPreference.SECONDARY_PREFERRED)
|
|
|
|
|
else:
|
|
|
|
|
self.assertNotEqual(bars._CommandCursor__collection.read_preference,
|
|
|
|
|
ReadPreference.SECONDARY_PREFERRED)
|
|
|
|
|
|
|
|
|
|
def test_json_simple(self):
|
|
|
|
|
|
|
|
|
|
class Embedded(EmbeddedDocument):
|
|
|
|
|
@@ -4493,8 +4607,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
users = User.objects.only('name', 'price').as_pymongo()
|
|
|
|
|
results = list(users)
|
|
|
|
|
self.assertTrue(isinstance(results[0], dict))
|
|
|
|
|
self.assertTrue(isinstance(results[1], dict))
|
|
|
|
|
self.assertIsInstance(results[0], dict)
|
|
|
|
|
self.assertIsInstance(results[1], dict)
|
|
|
|
|
self.assertEqual(results[0]['name'], 'Bob Dole')
|
|
|
|
|
self.assertEqual(results[0]['price'], 1.11)
|
|
|
|
|
self.assertEqual(results[1]['name'], 'Barack Obama')
|
|
|
|
|
@@ -4502,8 +4616,8 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
users = User.objects.only('name', 'last_login').as_pymongo()
|
|
|
|
|
results = list(users)
|
|
|
|
|
self.assertTrue(isinstance(results[0], dict))
|
|
|
|
|
self.assertTrue(isinstance(results[1], dict))
|
|
|
|
|
self.assertIsInstance(results[0], dict)
|
|
|
|
|
self.assertIsInstance(results[1], dict)
|
|
|
|
|
self.assertEqual(results[0], {
|
|
|
|
|
'name': 'Bob Dole'
|
|
|
|
|
})
|
|
|
|
|
@@ -4560,12 +4674,10 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
User(name="Bob Dole", organization=whitehouse).save()
|
|
|
|
|
|
|
|
|
|
qs = User.objects()
|
|
|
|
|
self.assertTrue(isinstance(qs.first().organization, Organization))
|
|
|
|
|
self.assertFalse(isinstance(qs.no_dereference().first().organization,
|
|
|
|
|
Organization))
|
|
|
|
|
self.assertFalse(isinstance(qs.no_dereference().get().organization,
|
|
|
|
|
Organization))
|
|
|
|
|
self.assertTrue(isinstance(qs.first().organization, Organization))
|
|
|
|
|
self.assertIsInstance(qs.first().organization, Organization)
|
|
|
|
|
self.assertNotIsInstance(qs.no_dereference().first().organization, Organization)
|
|
|
|
|
self.assertNotIsInstance(qs.no_dereference().get().organization, Organization)
|
|
|
|
|
self.assertIsInstance(qs.first().organization, Organization)
|
|
|
|
|
|
|
|
|
|
def test_no_dereference_embedded_doc(self):
|
|
|
|
|
|
|
|
|
|
@@ -4598,9 +4710,9 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
result = Organization.objects().no_dereference().first()
|
|
|
|
|
|
|
|
|
|
self.assertTrue(isinstance(result.admin[0], (DBRef, ObjectId)))
|
|
|
|
|
self.assertTrue(isinstance(result.member.user, (DBRef, ObjectId)))
|
|
|
|
|
self.assertTrue(isinstance(result.members[0].user, (DBRef, ObjectId)))
|
|
|
|
|
self.assertIsInstance(result.admin[0], (DBRef, ObjectId))
|
|
|
|
|
self.assertIsInstance(result.member.user, (DBRef, ObjectId))
|
|
|
|
|
self.assertIsInstance(result.members[0].user, (DBRef, ObjectId))
|
|
|
|
|
|
|
|
|
|
def test_cached_queryset(self):
|
|
|
|
|
class Person(Document):
|
|
|
|
|
@@ -4641,18 +4753,27 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
for i in range(100):
|
|
|
|
|
Person(name="No: %s" % i).save()
|
|
|
|
|
|
|
|
|
|
with query_counter() as q:
|
|
|
|
|
self.assertEqual(q, 0)
|
|
|
|
|
people = Person.objects.no_cache()
|
|
|
|
|
with query_counter() as q:
|
|
|
|
|
try:
|
|
|
|
|
self.assertEqual(q, 0)
|
|
|
|
|
people = Person.objects.no_cache()
|
|
|
|
|
|
|
|
|
|
[x for x in people]
|
|
|
|
|
self.assertEqual(q, 1)
|
|
|
|
|
[x for x in people]
|
|
|
|
|
self.assertEqual(q, 1)
|
|
|
|
|
|
|
|
|
|
list(people)
|
|
|
|
|
self.assertEqual(q, 2)
|
|
|
|
|
list(people)
|
|
|
|
|
self.assertEqual(q, 2)
|
|
|
|
|
|
|
|
|
|
people.count()
|
|
|
|
|
self.assertEqual(q, 3)
|
|
|
|
|
except AssertionError as exc:
|
|
|
|
|
db = get_db()
|
|
|
|
|
msg = ''
|
|
|
|
|
for q in list(db.system.profile.find())[-50:]:
|
|
|
|
|
msg += str([q['ts'], q['ns'], q.get('query'), q['op']])+'\n'
|
|
|
|
|
msg += str(q)
|
|
|
|
|
raise AssertionError(str(exc) + '\n'+msg)
|
|
|
|
|
|
|
|
|
|
people.count()
|
|
|
|
|
self.assertEqual(q, 3)
|
|
|
|
|
|
|
|
|
|
def test_cache_not_cloned(self):
|
|
|
|
|
|
|
|
|
|
@@ -4795,6 +4916,30 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
for obj in C.objects.no_sub_classes():
|
|
|
|
|
self.assertEqual(obj.__class__, C)
|
|
|
|
|
|
|
|
|
|
def test_query_generic_embedded_document(self):
|
|
|
|
|
"""Ensure that querying sub field on generic_embedded_field works
|
|
|
|
|
"""
|
|
|
|
|
class A(EmbeddedDocument):
|
|
|
|
|
a_name = StringField()
|
|
|
|
|
|
|
|
|
|
class B(EmbeddedDocument):
|
|
|
|
|
b_name = StringField()
|
|
|
|
|
|
|
|
|
|
class Doc(Document):
|
|
|
|
|
document = GenericEmbeddedDocumentField(choices=(A, B))
|
|
|
|
|
|
|
|
|
|
Doc.drop_collection()
|
|
|
|
|
Doc(document=A(a_name='A doc')).save()
|
|
|
|
|
Doc(document=B(b_name='B doc')).save()
|
|
|
|
|
|
|
|
|
|
# Using raw in filter working fine
|
|
|
|
|
self.assertEqual(Doc.objects(
|
|
|
|
|
__raw__={'document.a_name': 'A doc'}).count(), 1)
|
|
|
|
|
self.assertEqual(Doc.objects(
|
|
|
|
|
__raw__={'document.b_name': 'B doc'}).count(), 1)
|
|
|
|
|
self.assertEqual(Doc.objects(document__a_name='A doc').count(), 1)
|
|
|
|
|
self.assertEqual(Doc.objects(document__b_name='B doc').count(), 1)
|
|
|
|
|
|
|
|
|
|
def test_query_reference_to_custom_pk_doc(self):
|
|
|
|
|
|
|
|
|
|
class A(Document):
|
|
|
|
|
@@ -4919,7 +5064,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
op = q.db.system.profile.find({"ns":
|
|
|
|
|
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
|
|
|
|
|
|
|
|
|
self.assertFalse('$orderby' in op['query'],
|
|
|
|
|
self.assertNotIn('$orderby', op['query'],
|
|
|
|
|
'BaseQuerySet cannot use orderby in if stmt')
|
|
|
|
|
|
|
|
|
|
with query_counter() as p:
|
|
|
|
|
@@ -4930,8 +5075,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
op = p.db.system.profile.find({"ns":
|
|
|
|
|
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
|
|
|
|
|
|
|
|
|
self.assertTrue('$orderby' in op['query'],
|
|
|
|
|
'BaseQuerySet cannot remove orderby in for loop')
|
|
|
|
|
self.assertIn('$orderby', op['query'], 'BaseQuerySet cannot remove orderby in for loop')
|
|
|
|
|
|
|
|
|
|
def test_bool_with_ordering_from_meta_dict(self):
|
|
|
|
|
|
|
|
|
|
@@ -4955,7 +5099,7 @@ class QuerySetTest(unittest.TestCase):
|
|
|
|
|
op = q.db.system.profile.find({"ns":
|
|
|
|
|
{"$ne": "%s.system.indexes" % q.db.name}})[0]
|
|
|
|
|
|
|
|
|
|
self.assertFalse('$orderby' in op['query'],
|
|
|
|
|
self.assertNotIn('$orderby', op['query'],
|
|
|
|
|
'BaseQuerySet must remove orderby from meta in boolen test')
|
|
|
|
|
|
|
|
|
|
self.assertEqual(Person.objects.first().name, 'A')
|
|
|
|
|
|