MongoDB 学习笔记(一):创建文档

133 阅读4分钟

一、创建文档

1. 进入Mongo shell

# 使用test数据库
> use test
switched to db test

# 查看test数据库中的集合
> show collections

2. 创建一个文档

db.<集合名>.inserOne(文档内容) 命令会自动创建相应的集合
> db.accounts.insertOne(
... {
...    _id: "account1",
...   name: "alice",
...   balance: 100
... }
... )
{ "acknowledged" : true, "insertedId" : "account1" }  
  • { "acknowledged" : true, "insertedId" : "account1" }:
    • 是返回的结果
    • "acknowledged": true表示安全写级别被启用
    • "insertedId":显示了被写入的文档的_id

2.1 使用重复_id创建一个新文档会造成错误

# 为了方便查看错误信息,最好加上try catch

try{
        db.accounts.insertOne(
            {
                _id:"account1",
                name:"bob",
                balance: 50
            }
        ) 
    }catch(e) {
        print(e)
    }
    
    
# 错误

WriteError({
        "index" : 0,
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.accounts index: _id_ dup key: { _id: \"account1\" }",
        "op" : {
                "_id" : "account1",
                "name" : "bob",
                "balance" : 50
        }

2.2 自动生成_id

 省略创建文档中的_id字段
 
db.accounts.insertOne(
    {
        name:"bob",
        balance:50
    }
)
# 返回结果
{
        "acknowledged" : true,
            "insertedId" : ObjectId("63bd080fef3b5e682a151ff8")# 自动生成的文档主键
}

3. 创建多个文档

db.collection.insertMany()

db.<collection>.insertMany(
    [<document1>,<document2>,...],
    {
        writeConcern:<document>,
        ordered:<boolean>
    }
)
ordered参数用来决定mongoDB 是否按顺序来写入这些文档

ordered设置为false,则打乱文档写入的顺序,以便优化写入操作的性能,默认为true
db.accounts.insertMany(
    [
        {
            name:"charlie",
            balance:500
        },
        {
            name:"david",
            balance:200
        }
    ]
)

# 返回结果
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("63bd1a23ef3b5e682a151ff9"),
                ObjectId("63bd1a23ef3b5e682a151ffa")
        ]
}

使用重复的_id,顺序写入时遇到的错误

# # 第一个文档用重复的_id
try{
    db.accounts.insertMany(
        [
            {
                _id:"account1",   
                name:"edwrad",
                balance:700
            },
            {
                name:"david",
                balance:20
            }
        ]
    )
}  catch(e) {
    print(e)
}


# 报错信息

BulkWriteError({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 11000,
                        "errmsg" : "E11000 duplicate key error collection: test.accounts index: _id_ dup key: { _id: \"account1\" }",
                        "op" : {
                                "_id" : "account1",
                                "name" : "edwrad",
                                "balance" : 700
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 0,     # 因为是顺序写入,所以一篇都没插进去,直接开始报错了,所以是0
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

使用重复_id,乱序写入时遇到的错误

# 设置为乱序
try{
    db.accounts.insertMany(
        [
            {
                _id:"account1",   
                name:"edwrad",
                balance:700
            },
            {
                name:"david",
                balance:20
            }
        ],{ ordered:false } 
    )
}  catch(e) {
    print(e)
}


# 报错信息

BulkWriteError({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 11000,
                        "errmsg" : "E11000 duplicate key error collection: test.accounts index: _id_ dup key: { _id: \"account1\" }",
                        "op" : {
                                "_id" : "account1",
                                "name" : "edwrad",
                                "balance" : 700
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 1,   # 因为是乱序写入,第二篇成功了,第一篇失败了,所以成功插入数量为1
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

在顺序写入时,一旦遇到错误,操作便会退出,剩余的文档无论正确与否,都不会被写入。

在乱序写入时。即使某些文档造成了错误,剩余得正确文档仍然会被写入

4. 创建一个或多个文档

db.collection.insert()

db.<collection>.insert(
    <document or array of documents>,# 一个或多个文档
    {
        writeConcern:<document>,
        ordered:<boolean>
    }
)

将文档吸入accounts集合

db.accounts.insert(
    {
        name:"george",
        balance:1000
    }
)

# 只返回写入文档的数量
WriteResult({ "nInserted" : 1 })

使用insert插入重复的_id

try{
    db.accounts.insert(
        [
            {
                _id:"account1",
                name:"george",
                balance:1000
            },
            {
                name:"henry",
                balance:2000
            }
        ]
    )
} catch(e){
    print(e)
}

# 报错
BulkWriteResult({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 11000,
                        "errmsg" : "E11000 duplicate key error collection: test.accounts index: _id_ dup key: { _id: \"account1\" }",
                        "op" : {
                                "_id" : "account1",
                                "name" : "george",
                                "balance" : 1000
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 0,  # 跟之前的顺序插入多个一样
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

5. insertOne,insertMany和insert的区别

  • 返回的结果文档格式不一样(具体看上面例子)
  • insertOneinsertMany命令不支持db.collection.explain()命令,但是insert支持

6. 另一个创建文档的命令

db.collection.save()

db.<collection>.save(
    <document>,
    {
        writeConcern:<document>
    }
)

当这个命令处理一个新文档的时候,它会调用insert()命令,且返回的结果文档与insert()一样

6. 文档主键_id

在不主动指定_id的情况下,默认的对象主键objectId

# 创建一个主键
> ObjectId()
ObjectId("63bd2997ef3b5e682a151fff")
# 知道主键id并查看
> ObjectId("63bd2997ef3b5e682a151fff")
ObjectId("63bd2997ef3b5e682a151fff")
# 提取ObjectId的创建时间
> ObjectId("63bd2997ef3b5e682a151fff").getTimestamp()
ISODate("2023-01-10T09:02:15Z")

7. 复合主键

  • 可以使用文档作为文档主键
# _id本身就是一个文档
db.accounts.insert(
    {
        _id:{ accountNo:"001",type:"savings"},
        name:"irene",
        balance:80
    }
)
  • 复合主键仍然要满足文档主键的唯一性
  • 当复合主键的文档内容一样,但是顺序不一样时,也满足唯一性
# 顺序不同,两个复合id依旧满足唯一性
_id:{ accountNo:"001",type:"savings"}
_id:{ type:"savings",accountNo:"001"}

8. 总结

  • 使用db.collection.insertOne()创建单一文档
  • 使用db.collection.insertMany()创建多个文档
  • 使用db.collection.insert()创建单一或多个文档
  • 创建文档命令返回的结果/错误
  • 使用db.collection.save()创建单一文档
  • 对象主键ObjectId
  • 复合主键