Mongo DB中save和insert有什么区别?

180

Mongo DB 中的 save 和 insert 有什么区别?两者看起来很相似。

db.users.save({username:"google",password:"google123"})

db.users.insert({username:"google",password:"google123"})

http://docs.mongodb.org/manual/reference/method/db.collection.save/#db.collection.save - Tushar Mishra
2
请注意,pymongo中的save()现已过时。 - Gabriel Fair
9个回答

174

保存 vs 插入:

在你提供的示例中,其行为本质上是相同的。

save如果传递了一个"_id"参数,则会表现出不同的行为。

对于save,如果文档包含_id,它将查询_id字段的集合进行更新,否则它将进行插入。

如果不存在指定_id值的文档,则save()方法使用文档中指定的字段执行插入操作。

如果存在指定_id值的文档,则save()方法执行更新操作,用文档中的字段替换现有记录中的所有字段。


保存 vs 更新:

update修改与您的查询参数匹配的现有文档。如果没有这样的匹配文档,那么upsert就会出现问题。

  • upsert: false: 当没有这样的文档存在时,什么都不会发生
  • upsert: true: 新文档将被创建,其内容等于查询参数和更新参数

save : 不允许任何查询参数。如果_id存在并且具有相同_id的匹配文档,则替换它。当没有指定_id或没有匹配的文档时,将其作为新文档插入。


9
两者具有不同的语法。Update 接受多个参数 ({condition},{update to doc}, upsert, multi),而 save 只接受一个参数(_id 作为条件参数)。Update 可以接受任意条件,但 save 的条件限制只能在 _id 字段上。 - Rahul
1
从2.6版本开始,save方法有第二个参数,接受一个表示写入关注的文档。http://docs.mongodb.org/manual/reference/method/db.collection.save/ - huggie

119

让我们考虑以下两种情况以实现保存:-

1)文档中有_id。

2)文档中没有_id。

                        Save ()
                        /     \
                       /       \

                 Having _id     Not Having _id 

  ->In this case save will do    ->  It will do normal insertion 
    upsert to insert.Now             in this case as insert() do.
    what that means, it means 
    take the document and replace 
    the complete document having same
    _id.

让我们在这里考虑插入的两种情况:

1)已经在集合中存在文档的_id。

2)集合中没有文档的_id。

                        Insert()
                       /        \
                      /          \

   Doc Having _id in collection    Doc Not Having _id 
  ->  E11000 duplicate key     ->Insert a new doc inside the collection.
      error index:       

31
下一级别的图表 - John Spiteri
9
感谢您花费时间绘制和呈现图表,我已给予点赞。 - fanbondi
3
GG 图表 - CᴴᴀZ
1
注意:从MongoDB 4.2开始,db.collection.save()方法已被弃用。请改用db.collection.insertOne()db.collection.replaceOne() - Serhii Popov

38

save 保存或更新文档。

insert 仅执行插入操作。

但在您的情况下,由于在保存的文档中没有_id字段,因此它将执行相同的操作。


14

通过举例说明

保存一个苹果

db.fruit.save({"name":"apple", "color":"red","shape":"round"})
WriteResult({ "nInserted" : 1 })

db.fruit.find();

{
    "_id" : ObjectId("53fa1809132c1f084b005cd0"),
    "color" : "red",
    "shape" : "round",
    "name" : "apple"
}

保存之前已保存苹果的ID为_id

db.fruit.save(
{"_id" : ObjectId("53fa1809132c1f084b005cd0"),"name":"apple", 
"color":"real red","shape":"round"})

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

现在我们保存的苹果,颜色已经从红色更新为真正的红色。


db.fruit.find();
{
    "_id" : ObjectId("53fa1809132c1f084b005cd0"),
    "color" : "real red",
    "shape" : "round",
    "name" : "apple"
}

保存带有 _id 的苹果

db.fruit.save({"_id" : ObjectId("55551809132c1f084b005cd0"),
"name":"apple", "color":"real red","shape":"round"})

    WriteResult({ "nMatched" : 0, "nUpserted" : 1, 
"nModified" : 0, "_id": 55551809132c1f084b005cd0 })

由于不存在具有相同对象ID的苹果,因此插入了苹果

插入一个橙子

db.fruit.insert({"name":"orange", "color":"orange","shape":"round"})
WriteResult({ "nInserted" : 1 })

橙色被插入了

db.fruit.find();
{
    "_id" : ObjectId("53fa1809132c1f084b005cd0"),
    "color" : "real red",
    "shape" : "round",
    "name" : "apple"
}
{
    "_id" : ObjectId("53fa196d132c1f084b005cd7"),
    "color" : "orange",
    "shape" : "round",
    "name" : "orange"
}
{
    "_id" : ObjectId("55551809132c1f084b005cd0"),
    "color" : "real red",
    "shape" : "round",
    "name" : "apple"
}

如果提供了对象ID并且对象ID已经存在,则save操作将充当更新,否则它将进行插入。


11

如果您尝试在同一集合中使用先前使用过的ID并使用“insert”,则会出现重复键错误。如果您使用的ID已经存在于同一集合中,则使用“save”将对其进行更新/覆盖。

如果您想要进行真正的更新,我建议使用“update”。如果您正在使用相同ID保存时,Update不会像Save那样进行覆盖,它只会更新该ID的数据。

例如,如果您有两个字段“x”和“y”,并且您想要保留这两个字段但更改“x”的值。如果您选择“save”命令并且没有包括先前值为y的y,或者根本没有包含y,则y将不再具有相同的值或存在。但是,如果您选择使用$set进行更新,并且只在您的更新语句中包含了x,则您不会影响到y。


6

3
考虑下面的文档:
{ "_id" : 1, "domainName" : "test1.com", "hosting" : "hostgator.com" }

如果数据库已经包含了_id为1的文档,则保存操作会抛出以下异常。
E11000 duplicate key error index ...........

而插入操作只会覆盖文档。


db.collection.save() 方法会在数据库中已经存在一个具有相同 _id 的文档时更新该文档。当数据库中已经存在一个具有相同 _id 的文档时,save 方法将完全替换该文档为新文档。来自书籍《Pro MongoDB Development》。 - jack blank

1

db.<collection_name>.save(<Document>) 相当于插入或更新查询。

db.<collection_name>.insert(<Document>) 则相当于仅插入查询。


1

关于ORACLE: mongo insert => Oracle插入 mongo save => Oracle合并


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接