请看下文。
MongoDB中ObjectId的误区及引起的一系列问题
什么是ObjectId
先来了解一下什么是ObjectId。
在MongoDB中,每一条记录(也可以理解为一条数据)都会有一个_id字段,这个字段的值是ObjectId类型。它类似于uuid或者GUID这样的工具,可以生成唯一的标识符。在最初的设计时,是为了在分布式环境下保证数据的唯一性而出现的。
它的具体实现方式是12字节的二进制数,其中前4个字节为时间戳,接下来的3个字节为机器标识符,然后是2个字节的进程id,最后是3个字节的自增计数值。这种设计保证了生成的ObjectId在单机、分布式环境下都是唯一的。
ObjectId的误区
ObjectId不是字符串类型
虽然在数据库中它是以字符串的形式呈现,但是它并不是真正的字符串类型。如果你尝试对ObjectId进行字符串的相关操作,比如切割、转换大小写,或者进行比较等,可能会引发一系列问题。
在Python中使用PyMongo库来进行数据操作的时候,会将ObjectId自动转成bson.objectid.ObjectId类型的对象。此时如果想进行字符串操作,需要先将它转成字符串,例如:str(ObjectId)
。
ObjectId由MongoDB生成
如果你在代码中自己手写ObjectId,MongoDB可能会拒绝它。ObjectId的生成需要遵循一定的规则,手写很难满足这些规则。
使用MongoDB中的insert或者save方法写入数据时,MongoDB会自动生成ObjectId,插入数据的时候可以不用指定_id字段,MongoDB会自动加上。这时,_id字段在数据库中默认是唯一的。
ObjectId仅在单个集合内唯一
ObjectId只能保证在单个集合内唯一,并不能保证全库的唯一性。 如果你跨越多个集合或数据库使用ObjectId,则需要自己实现全局唯一性的保证。
ObjectId的用法
ObjectId的创建方法
在MongoDB下,ObjectId的创建方式是非常简单的,只需要调用ObjectId的构造器即可。推荐使用以下方法:
from bson import ObjectId
new_id = ObjectId()
ObjectId的查询方法
一般情况下,我们通过一个文档对象的_id属性来调用数据。下面是一个通过_id进行简单查询的示例。
C语言驱动:
mongo_cursor cursor;
if (mongo_cursor_find(&cursor, "my_db.products", \
bson_init(&query), bson_init(NULL)) == MONGO_OK) {
while (mongo_cursor_next(&cursor) == MONGO_OK) {
bson_oid_t *oid;
bson_iterator it;
oid = bson_iterator_oid(&it);
printf("found: %s\n", oid);
}
}
Python驱动:
from bson import ObjectId
post_id = request.GET.get('post_id')
post = get_document_by_id('posts', post_id)
示例说明
示例一
假设有如下的一条记录:
{
"_id": {
"$oid": "5ec266e9c4698262ea6ebb23"
},
"name": "张三",
"age": 20,
"sex": "男"
}
如果我们想要获取这条记录的_id,可以直接进行访问,例如:
record = db.collection.find_one({"name": "张三"})
record_id = record['_id']
如果想要进行字符串操作,需要将其转化成字符串类型:
str(record_id)
示例二
假设我们想要查询一个名为"abc"的用户在不同的集合中是否存在,可以使用ObjectId实现。
第一种方式:
from bson import ObjectId
user_id = ObjectId('5ebff15acf72bdb1dc18da9a')
user_exists = any(db1.collection.find_one({"_id": user_id}) or db2.collection.find_one({"_id": user_id}))
第二种方式:
from bson import ObjectId
users = db.collection.aggregate([{'$group': {'_id': '$_id'}}])
user_ids = [str(user['_id']) for user in users]
user_id = ObjectId('5ebff15acf72bdb1dc18da9a')
user_exists = str(user_id) in user_ids
总结
- 在使用ObjectId的时候,一定要知道它的基本特性,以免出现一些误区和问题。
- 尽可能避免直接操作ObjectId,而是通过调用相应的方法来操作它。
- 可以使用ObjectId来实现基础的查重功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MongoDB中ObjectId的误区及引起的一系列问题 - Python技术站