MongoDB中ObjectId的误区及引起的一系列问题

请看下文。

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技术站

(0)
上一篇 2023年5月21日
下一篇 2023年5月21日

相关文章

  • Redis 实现广播订阅

    RedisHelper import redis class RedisHelper: def __init__(self): self.__conn = redis.Redis(host=’47.94.18.xxx’) self.chan_sub = ‘104.5’ # 接收频道 self.chan_pub = ‘104.5’ # 发送频道 def pub…

    Redis 2023年4月13日
    00
  • 实例介绍SQL注入以及如何解决

    我们来详细讲解一下“实例介绍SQL注入以及如何解决”的完整攻略。 什么是SQL注入 SQL注入是一种攻击方式,攻击者通过非法构造的输入,伪造或利用应用程序的逻辑漏洞,通过从应用程序的数据库中查询或操纵数据,来达到破坏目的的一种攻击手段。 攻击者通过输入恶意的SQL查询语句,绕过应用程序的身份验证和授权控制,直接访问数据库。攻击者可以利用这种缺陷,窃取、修改、…

    database 2023年5月18日
    00
  • Oracle Table Demo语句应用介绍

    请看下面的详细讲解。 什么是Oracle Table Demo语句 Oracle Table Demo语句是一种在Oracle数据库中用于创建和操作表格的语句。它能够快速实现基本表格的创建、查询、更新和删除功能,并且可以通过一定的参数设置实现高级的功能。 Oracle Table Demo语法规则 Oracle Table Demo语句的语法规则如下: –…

    database 2023年5月21日
    00
  • SQL语句的各个关键字的解析过程详细总结

    请听我详细讲解SQL语句中各个关键字的解析过程详细总结。 SQL语句的解析过程 SQL语句的解析过程包括语法分析和语义分析两个阶段。 1. 语法分析 语法分析是将SQL语句分解为不同的语法结构,识别其中的关键字、表名、列名、函数等元素,生成语法树。 语法分析器会检查SQL语句的正确性,主要包括以下几个方面: 语法是否符合规范,是否有拼写错误。 表名、列名是否…

    database 2023年5月21日
    00
  • Oracle中使用Rownum分页详细例子

    下面是关于“Oracle中使用Rownum分页详细例子”的完整攻略: 概述 Rownum是Oracle中的一个伪列,它可以将每一行按照其插入顺序赋予一个唯一的行号。通过使用Rownum,我们可以在Oracle数据库中方便地实现分页查询功能。本攻略将介绍如何使用Rownum完成分页查询。 步骤 1. 建立测试表 首先,我们需要建立一个测试表来演示分页查询。如下…

    database 2023年5月21日
    00
  • Linux环境下安装mysql5.7.36数据库教程

    下面是“Linux环境下安装mysql5.7.36数据库教程”的完整攻略,过程中包含两条示例说明。 准备工作 在开始安装mysql之前,需要先进行一些准备工作,包括安装依赖库、创建mysql用户等等。这些工作可以简单地通过下列命令完成: sudo apt-get update sudo apt-get install -y mysql-server mysq…

    database 2023年5月22日
    00
  • 聊聊spring @Transactional 事务无法使用的可能原因

    来聊聊Spring中@Transactional事务无法正常使用的可能原因。 1. 被注解的方法必须是public方法 注解@Transactional只能够应用于public方法之上。如果把这个注解用在一个非public的方法上面,它将被忽略。比如: // 正确写法 @Transactional public void save(Item item) { …

    database 2023年5月21日
    00
  • Oracle 获取上周一到周末日期的查询sql语句

    获取上周一到周末日期的查询 SQL 语句,可以采用以下两种方法实现: 方法一:使用 to_char 函数与日期函数来获取上周一和周日的日期,然后使用 BETWEEN 运算符来筛选上周一到周日的数据。 SELECT * FROM your_table WHERE your_date_column BETWEEN to_date(to_char(sysdate-…

    database 2023年5月21日
    00
合作推广
合作推广
分享本页
返回顶部