def test_create_geohaystack_index(self): """Ensure that geohaystack indexes can be created""" class Place(Document): location = DictField() name = StringField() if PYMONGO_VERSION >= (4, ): expected_error = NotImplementedError elif get_mongodb_version() >= (4, 9): expected_error = OperationFailure else: expected_error = None # This test can be removed when pymongo 3.x is no longer supported if expected_error: with pytest.raises(expected_error): Place.create_index( {"fields": (")location.point", "name")}, bucketSize=10, ) else: Place.create_index({"fields": (")location.point", "name")}, bucketSize=10) info = Place._get_collection().index_information() info = [value["key"] for key, value in info.items()] assert [("location.point", "geoHaystack"), ("name", 1)] in info
def _inner(*args, **kwargs): mongodb_v = get_mongodb_version() if oper(mongodb_v, mongo_version_req): return func(*args, **kwargs) pretty_version = ".".join(str(n) for n in mongo_version_req) pytest.skip(f"Needs MongoDB v{pretty_version}+")
def _inner(*args, **kwargs): mongodb_v = get_mongodb_version() if oper(mongodb_v, mongo_version_req): return func(*args, **kwargs) raise SkipTest('Needs MongoDB v{}+'.format('.'.join( str(n) for n in mongo_version_req)))
def test_covered_index(self): """Ensure that covered indexes can be used """ IS_MONGODB_3 = get_mongodb_version() >= MONGODB_3 class Test(Document): a = IntField() b = IntField() meta = {'indexes': ['a'], 'allow_inheritance': False} Test.drop_collection() obj = Test(a=1) obj.save() # Need to be explicit about covered indexes as mongoDB doesn't know if # the documents returned might have more keys in that here. query_plan = Test.objects(id=obj.id).exclude('a').explain() if not IS_MONGODB_3: self.assertFalse(query_plan['indexOnly']) else: self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get( 'inputStage').get('stage'), 'IDHACK') query_plan = Test.objects(id=obj.id).only('id').explain() if not IS_MONGODB_3: self.assertTrue(query_plan['indexOnly']) else: self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get( 'inputStage').get('stage'), 'IDHACK') query_plan = Test.objects(a=1).only('a').exclude('id').explain() if not IS_MONGODB_3: self.assertTrue(query_plan['indexOnly']) else: self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get( 'inputStage').get('stage'), 'IXSCAN') self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'PROJECTION') query_plan = Test.objects(a=1).explain() if not IS_MONGODB_3: self.assertFalse(query_plan['indexOnly']) else: self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get( 'inputStage').get('stage'), 'IXSCAN') self.assertEqual( query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'FETCH')
def test_keys_with_dots_or_dollars(self): class BlogPost(Document): info = DictField() BlogPost.drop_collection() post = BlogPost() post.info = {"$title": "test"} with pytest.raises(ValidationError): post.validate() post.info = {"nested": {"$title": "test"}} with pytest.raises(ValidationError): post.validate() post.info = {"$title.test": "test"} with pytest.raises(ValidationError): post.validate() post.info = {"nested": {"the.title": "test"}} if get_mongodb_version() < MONGODB_36: # MongoDB < 3.6 rejects dots # To avoid checking the mongodb version from the DictField class # we rely on MongoDB to reject the data during the save post.validate() with pytest.raises(InvalidDocument): post.save() else: post.validate() post.info = {"dollar_and_dot": {"te$st.test": "test"}} if get_mongodb_version() < MONGODB_36: post.validate() with pytest.raises(InvalidDocument): post.save() else: post.validate()
def setUp(self): self.connection = connect(db='mongoenginetest') self.db = get_db() self.mongodb_version = get_mongodb_version() class Person(Document): name = StringField() age = IntField() non_field = True meta = {"allow_inheritance": True} self.Person = Person
def test_covered_index(self): """Ensure that covered indexes can be used """ IS_MONGODB_3 = get_mongodb_version() >= MONGODB_3 class Test(Document): a = IntField() b = IntField() meta = { 'indexes': ['a'], 'allow_inheritance': False } Test.drop_collection() obj = Test(a=1) obj.save() # Need to be explicit about covered indexes as mongoDB doesn't know if # the documents returned might have more keys in that here. query_plan = Test.objects(id=obj.id).exclude('a').explain() if not IS_MONGODB_3: self.assertFalse(query_plan['indexOnly']) else: self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IDHACK') query_plan = Test.objects(id=obj.id).only('id').explain() if not IS_MONGODB_3: self.assertTrue(query_plan['indexOnly']) else: self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IDHACK') query_plan = Test.objects(a=1).only('a').exclude('id').explain() if not IS_MONGODB_3: self.assertTrue(query_plan['indexOnly']) else: self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IXSCAN') self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'PROJECTION') query_plan = Test.objects(a=1).explain() if not IS_MONGODB_3: self.assertFalse(query_plan['indexOnly']) else: self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('inputStage').get('stage'), 'IXSCAN') self.assertEqual(query_plan.get('queryPlanner').get('winningPlan').get('stage'), 'FETCH')
def test_covered_index(self): """Ensure that covered indexes can be used""" class Test(Document): a = IntField() b = IntField() meta = {"indexes": ["a"], "allow_inheritance": False} Test.drop_collection() obj = Test(a=1) obj.save() # Need to be explicit about covered indexes as mongoDB doesn't know if # the documents returned might have more keys in that here. query_plan = Test.objects(id=obj.id).exclude("a").explain() assert (query_plan.get("queryPlanner").get("winningPlan").get( "inputStage").get("stage") == "IDHACK") query_plan = Test.objects(id=obj.id).only("id").explain() assert (query_plan.get("queryPlanner").get("winningPlan").get( "inputStage").get("stage") == "IDHACK") query_plan = Test.objects(a=1).only("a").exclude("id").explain() assert (query_plan.get("queryPlanner").get("winningPlan").get( "inputStage").get("stage") == "IXSCAN") mongo_db = get_mongodb_version() PROJECTION_STR = "PROJECTION" if mongo_db < MONGODB_42 else "PROJECTION_COVERED" assert (query_plan.get("queryPlanner").get("winningPlan").get("stage") == PROJECTION_STR) query_plan = Test.objects(a=1).explain() assert (query_plan.get("queryPlanner").get("winningPlan").get( "inputStage").get("stage") == "IXSCAN") assert query_plan.get("queryPlanner").get("winningPlan").get( "stage") == "FETCH"
def test_general_things(self): """Ensure that dict types work as expected.""" class BlogPost(Document): info = DictField() BlogPost.drop_collection() post = BlogPost() post.info = "my post" with pytest.raises(ValidationError): post.validate() post.info = ["test", "test"] with pytest.raises(ValidationError): post.validate() post.info = {"$title": "test"} with pytest.raises(ValidationError): post.validate() post.info = {"nested": {"$title": "test"}} with pytest.raises(ValidationError): post.validate() post.info = {"$title.test": "test"} with pytest.raises(ValidationError): post.validate() post.info = {1: "test"} with pytest.raises(ValidationError): post.validate() post.info = {"nested": {"the.title": "test"}} if get_mongodb_version() < MONGODB_36: with pytest.raises(ValidationError): post.validate() else: post.validate() post.info = {"dollar_and_dot": {"te$st.test": "test"}} if get_mongodb_version() < MONGODB_36: with pytest.raises(ValidationError): post.validate() else: post.validate() post.info = {"title": "test"} post.save() post = BlogPost() post.info = {"title": "dollar_sign", "details": {"te$t": "test"}} post.save() post = BlogPost() post.info = {"details": {"test": "test"}} post.save() post = BlogPost() post.info = {"details": {"test": 3}} post.save() assert BlogPost.objects.count() == 4 assert BlogPost.objects.filter(info__title__exact="test").count() == 1 assert BlogPost.objects.filter( info__details__test__exact="test").count() == 1 post = BlogPost.objects.filter( info__title__exact="dollar_sign").first() assert "te$t" in post["info"]["details"] # Confirm handles non strings or non existing keys assert BlogPost.objects.filter( info__details__test__exact=5).count() == 0 assert BlogPost.objects.filter( info__made_up__test__exact="test").count() == 0 post = BlogPost.objects.create(info={"title": "original"}) post.info.update({"title": "updated"}) post.save() post.reload() assert "updated" == post.info["title"] post.info.setdefault("authors", []) post.save() post.reload() assert [] == post.info["authors"]
def _inner(*args, **kwargs): mongodb_v = get_mongodb_version() if oper(mongodb_v, mongo_version_req): return func(*args, **kwargs) raise SkipTest('Needs MongoDB v{}+'.format('.'.join(str(n) for n in mongo_version_req)))