MongoDB _id

在MongoDB中,_id字段是表示一个集合的主键【类似MySQL中的id字段】,可以唯一标识每个文档。_id字段包含唯一的ObjectID值。

使用默认的_id(ObjectId)

默认情况下,在集合中插入文档时,如果字段名中没有_id的字段名称,则MongoDB将自动添加一个ObjectId字段。

ObjectId是轻量型的,不同的机器都能全局唯一的生成它;ObjectId使用12字节的存储空间。

各字节含义

0-3字节:表示时间戳
4-6:表示主机的唯一标识符。【确保不同主机生成的ObjectId是唯一的】
7-8:表示进程id。【确保同一机器上并发的多个进程产生的ObjectId是唯一的】
9-11:表示计数器。【确保同一机器上同一进程同一秒产生的ObjectId是唯一的】

好处:适用于分布式数据库

1
2
3
4
5
6
7
8
9
> db.jihe1.find().pretty().limit(1)
{
"_id" : ObjectId("5febdaec4747ad3af6c87d7b"),
"user_id" : 0,
"user_name" : "name0",
"user_password" : "password0",
"user_other" : "other0"
}
>

将ObjectId中的前四个字节的十六进制转换成十进制【5febdaed->1609292524】,表示的秒级别的时间戳。

将时间戳转换成日期的时间【1609292524->2020-12-30 09:42:04[北京时间]】

总结:

  1. ObjectId前9个字节提供了秒级别的唯一性。
  2. 当连续插入多个document的时候,会发现只有后面的3个字节在变化。

自定义_id字段

我们向一个集合中添加文档时,显示的创建“_id”字段时,文档中不会默认生成_id字段,而是使用我们指定的”_id”

1
2
3
4
5
6
7
8
9
10
11
12
> db.jihe1.insert({_id: 1, user_id: 0, user_name: "name00", user_password: "password00", user_other: "other00"})
WriteResult({ "nInserted" : 1 })
> db.jihe.find({_id: 1}).pretty()
> db.jihe1.find({_id: 1}).pretty()
{
"_id" : 1,
"user_id" : 0,
"user_name" : "name00",
"user_password" : "password00",
"user_other" : "other00"
}
>

MONGODB 数据的存储顺序发现不是按_ID

当把字段的值update时,字段的长度在逐步增加.因为MongoDB在记录长度变化后,发现当前记录所在空间后面没有空余的空间可供其变长。

那么这条记录就会被删除然后移动到数据集的最后,所以导致$natural最后排序的结果和之前不一样。

1
2
3
4
> db.test.find().sort({_id:1}).limit(1)
{ "_id" : 0, "a" : "1" }
> db.test.find().sort({$natural:1}).limit(1)
{ "_id" : 0, "a" : "1" }

修改数据

1
> db.test.update({},{a:'123456789012345678901234567890'})

下面看到结果了:可以看到原先的第一条记录,_id:0 存储顺序已发生了变化,已不是第一条记录了。

1
2
3
4
5
6
7
8
9
10
11
> db.test.find().sort({_id:1}).limit(2)
{ "_id" : 0, "a" : "123456789012345678901234567890" }
{ "_id" : 1, "a" : "1" }

> db.test.find().sort({$natural:1}).limit(2)
{ "_id" : 1, "a" : "1" }
{ "_id" : 2, "a" : "1" }

> db.test.find().limit(2)
{ "_id" : 1, "a" : "1" }
{ "_id" : 2, "a" : "1" }

python 生成 ObjectId

1
2
3
4
5
6
7
8
9
from bson.objectid import ObjectId


query_id_str = '5c00f60b20b531196c02d657'
find_condition = {
'_id' : ObjectId(query_id_str),
}
find_result = mongo_collection.find_one(find_condition)
print(find_result)

用 _id 比较

在数据库中可以直接用 _id 字段比较

1
db.test1.find({"_id":{"$lt":ObjectId(5c00f60b20b531196c02d657)}})

MongoDB _id
https://flepeng.github.io/041-MongoDB-MongoDB-id/
作者
Lepeng
发布于
2021年6月6日
许可协议