Exemple #1
0
    def _save_create(self, doc, force_insert, write_concern):
        """Save a new document.

        Helper method, should only be used inside save().
        """
        doc_alias = None
        if doc.get('properties', {}).get('db_alias', None):
            doc_alias = doc['properties'].pop('db_alias')
        if doc_alias:
            alias_db = get_db(doc_alias)
            collection = alias_db.get_collection(self._meta['collection'])
        else:
            collection = self._get_collection()
        with set_write_concern(collection, write_concern) as wc_collection:
            if force_insert:
                return wc_collection.insert_one(doc).inserted_id
            # insert_one will provoke UniqueError alongside save does not
            # therefore, it need to catch and call replace_one.
            if "_id" in doc:
                raw_object = wc_collection.find_one_and_replace(
                    {"_id": doc["_id"]}, doc)
                if raw_object:
                    return doc["_id"]

            object_id = wc_collection.insert_one(doc).inserted_id

        return object_id
Exemple #2
0
    def _save_create(self, doc, force_insert, write_concern):
        """Save a new document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        with set_write_concern(collection, write_concern) as wc_collection:
            if force_insert:
                return wc_collection.insert_one(doc).inserted_id
            # insert_one will provoke UniqueError alongside save does not
            # therefore, it need to catch and call replace_one.
            if '_id' in doc:
                raw_object = wc_collection.find_one_and_replace(
                    {'_id': doc['_id']}, doc)
                if raw_object:
                    return doc['_id']

            object_id = wc_collection.insert_one(doc).inserted_id

        # In PyMongo 3.0, the save() call calls internally the _update() call
        # but they forget to return the _id value passed back, therefore getting it back here
        # Correct behaviour in 2.X and in 3.0.1+ versions
        if not object_id and pymongo.version_tuple == (3, 0):
            pk_as_mongo_obj = self._fields.get(
                self._meta['id_field']).to_mongo(self.pk)
            object_id = (self._qs.filter(pk=pk_as_mongo_obj).first()
                         and self._qs.filter(pk=pk_as_mongo_obj).first().pk
                         )  # TODO doesn't this make 2 queries?

        return object_id
Exemple #3
0
    def _save_update(self, doc, save_condition, write_concern):
        """Update an existing document.

        Helper method, should only be used inside save().
        """
        doc_alias = None
        if doc.get('properties', {}).get('db_alias', None):
            doc_alias = doc['properties'].pop('db_alias')
            if doc.get('properties', {}).get('conn_settings', {}):
                connection_properties = doc['properties'].pop('conn_settings')
                self.verify_connection_setting(doc_alias,
                                               connection_properties)

        if doc_alias:
            alias_db = get_db(doc_alias)
            collection = alias_db.get_collection(self._meta['collection'])
        else:
            collection = self._get_collection()
        object_id = doc["_id"]
        created = False

        select_dict = {}
        if save_condition is not None:
            select_dict = transform.query(self.__class__, **save_condition)

        select_dict["_id"] = object_id

        # Need to add shard key to query, or you get an error
        shard_key = self._meta.get("shard_key", tuple())
        for k in shard_key:
            path = self._lookup_field(k.split("."))
            actual_key = [p.db_field for p in path]
            val = doc
            for ak in actual_key:
                val = val[ak]
            select_dict[".".join(actual_key)] = val

        update_doc = self._get_update_doc()
        if update_doc:
            upsert = save_condition is None
            with set_write_concern(collection, write_concern) as wc_collection:
                last_error = wc_collection.update_one(select_dict,
                                                      update_doc,
                                                      upsert=upsert).raw_result
            if not upsert and last_error["n"] == 0:
                raise SaveConditionError(
                    "Race condition preventing document update detected")
            if last_error is not None:
                updated_existing = last_error.get("updatedExisting")
                if updated_existing is False:
                    created = True
                    # !!! This is bad, means we accidentally created a new,
                    # potentially corrupted document. See
                    # https://github.com/MongoEngine/mongoengine/issues/564

        return object_id, created
Exemple #4
0
    def _save_update(self, doc, save_condition, write_concern):
        """Update an existing document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        object_id = doc['_id']
        created = False

        select_dict = {}
        if save_condition is not None:
            select_dict = transform.query(self.__class__, **save_condition)

        select_dict['_id'] = object_id

        # Need to add shard key to query, or you get an error
        shard_key = self._meta.get('shard_key', tuple())
        for k in shard_key:
            path = self._lookup_field(k.split('.'))
            actual_key = [p.db_field for p in path]
            val = doc
            for ak in actual_key:
                val = val[ak]
            select_dict['.'.join(actual_key)] = val

        update_doc = self._get_update_doc()
        if update_doc:
            upsert = save_condition is None
            with set_write_concern(collection, write_concern) as wc_collection:
                last_error = wc_collection.update_one(
                    select_dict,
                    update_doc,
                    upsert=upsert
                ).raw_result
            if not upsert and last_error['n'] == 0:
                raise SaveConditionError('Race condition preventing'
                                         ' document update detected')
            if last_error is not None:
                updated_existing = last_error.get('updatedExisting')
                if updated_existing is False:
                    created = True
                    # !!! This is bad, means we accidentally created a new,
                    # potentially corrupted document. See
                    # https://github.com/MongoEngine/mongoengine/issues/564

        return object_id, created
Exemple #5
0
    def test_set_write_concern(self):
        connect("mongoenginetest")

        class User(Document):
            name = StringField()

        collection = User._get_collection()
        original_write_concern = collection.write_concern

        with set_write_concern(
            collection, {"w": "majority", "j": True, "wtimeout": 1234}
        ) as updated_collection:
            assert updated_collection.write_concern.document == {
                "w": "majority",
                "j": True,
                "wtimeout": 1234,
            }

        assert original_write_concern.document == collection.write_concern.document
Exemple #6
0
    def _save_create(self, doc, force_insert, write_concern):
        """Save a new document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        with set_write_concern(collection, write_concern) as wc_collection:
            if force_insert:
                return wc_collection.insert_one(doc).inserted_id
            # insert_one will provoke UniqueError alongside save does not
            # therefore, it need to catch and call replace_one.
            if '_id' in doc:
                raw_object = wc_collection.find_one_and_replace(
                    {'_id': doc['_id']}, doc)
                if raw_object:
                    return doc['_id']

            object_id = wc_collection.insert_one(doc).inserted_id

        return object_id
Exemple #7
0
    def _save_create(self, doc, force_insert, write_concern):
        """Save a new document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        with set_write_concern(collection, write_concern) as wc_collection:
            if force_insert:
                return wc_collection.insert_one(doc).inserted_id
            # insert_one will provoke UniqueError alongside save does not
            # therefore, it need to catch and call replace_one.
            if '_id' in doc:
                raw_object = wc_collection.find_one_and_replace(
                    {'_id': doc['_id']}, doc)
                if raw_object:
                    return doc['_id']

            object_id = wc_collection.insert_one(doc).inserted_id

        return object_id
Exemple #8
0
    def _save_update(self, doc, save_condition, write_concern):
        """Update an existing document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        object_id = doc["_id"]
        created = False

        select_dict = {}
        if save_condition is not None:
            select_dict = transform.query(self.__class__, **save_condition)

        select_dict["_id"] = object_id

        select_dict = self._integrate_shard_key(doc, select_dict)

        update_doc = self._get_update_doc()
        if update_doc:
            upsert = save_condition is None
            with set_write_concern(collection, write_concern) as wc_collection:
                last_error = wc_collection.update_one(
                    select_dict,
                    update_doc,
                    upsert=upsert,
                    session=self._get_local_session(),
                ).raw_result
            if not upsert and last_error["n"] == 0:
                raise SaveConditionError(
                    "Race condition preventing document update detected")
            if last_error is not None:
                updated_existing = last_error.get("updatedExisting")
                if updated_existing is False:
                    created = True
                    # !!! This is bad, means we accidentally created a new,
                    # potentially corrupted document. See
                    # https://github.com/MongoEngine/mongoengine/issues/564

        return object_id, created
Exemple #9
0
    def _save_create(self, doc, force_insert, write_concern):
        """Save a new document.

        Helper method, should only be used inside save().
        """
        collection = self._get_collection()
        with set_write_concern(collection, write_concern) as wc_collection:
            if force_insert:
                return wc_collection.insert_one(
                    doc, session=self._get_local_session()).inserted_id
            # insert_one will provoke UniqueError alongside save does not
            # therefore, it need to catch and call replace_one.
            if "_id" in doc:
                select_dict = {"_id": doc["_id"]}
                select_dict = self._integrate_shard_key(doc, select_dict)
                raw_object = wc_collection.find_one_and_replace(
                    select_dict, doc, session=self._get_local_session())
                if raw_object:
                    return doc["_id"]

            object_id = wc_collection.insert_one(
                doc, session=self._get_local_session()).inserted_id

        return object_id