当前位置: 首页 > 知识库问答 >
问题:

使用自定义pk作为字符串是个坏主意吗?

冯星剑
2023-03-14

让我来解释一下这个问题。我使用node-mongoDB本地作为mongob驱动程序,每次我需要通过_id字段进行查找查询时,我必须将其转换为ObjectId,如下所示:

var ObjectID = require('mongodb').ObjectID;

db.collection.find({_id: new ObjectID('51b02413453078800a000001')}, 
       function (err, docs) {
           ...
       });

我不想对每一个请求都使用ObjectID。到目前为止,我找到的唯一解决方案是将自定义ObjectID生成为字符串,如下所示:

var CustomPKFactory = {
   createPk: function() {
    return new ObjectID().toString();
   }
};

var mongoClient = new MongoClient(new Server('localhost', 27017), {   
   pk: CustomPKFactory,
});

在本例中,我将_id作为字符串,不需要分别将其转换为ObjectID。但我不知道这将如何影响查询性能。

你能告诉我这种方法的优点和缺点吗?

共有1个答案

步建茗
2023-03-14

默认情况下,字符串的大小将更大,正如Sammaye在注释中描述的那样。要将其形式化:

Object.bsonsize({ "_id" : ObjectId("51b10b55f202d3fee925d637")}) = 22 
Object.bsonsize({ "_id" : "51b10b55f202d3fee925d637"}) = 39
Object.bsonsize({ "_id" : "aaaaaaa"}) = 22
Object.bsonsize({ "_id" : 9999999999999998 }) = 18

所以一个7字符长的字符串与ObjectId大小相同。如果你使用的数字较小,但你必须考虑这一点:

我发现,在mongoshell中,输入是自动的,而数字类型之间的转换是自动的,这非常有趣。所以基本上,你可以存储为“整数”的最大数字(至少是格式)是999999999999 8,这有点奇怪,但它不应该与十进制表示有关(实际上BSON数据类型是双精度的)。上述所有数字都会自动转换并四舍五入为标准形式,例如:

{_id:9999999999999999} 

将存储为:1e 16.0,它是一个四舍五入的值,所以当你试图插入:

insert({_id:10000000000000001})
E11000 duplicate key error index: $_id_  dup key: { : 1e+16.0 }

我正在考虑提交一个bug。

这种情况甚至值得使用NumberLong()类型,即64位整数BSON类型:

> db.m.insert({_id: NumberLong(10000000000000001)})
E11000 duplicate key error index: t.m.$_id_  dup key: { : 10000000000000000 }
> db.m.insert({_id: NumberLong(10000000000000002)})
> db.m.insert({_id: NumberLong(10000000000000003)})
> db.m.insert({_id: NumberLong(10000000000000004)})
E11000 duplicate key error index: t.m.$_id_  dup key: { : 10000000000000004 }
> db.m.insert({_id: NumberLong(10000000000000005)})
E11000 duplicate key error index: t.m.$_id_  dup key: { : 10000000000000004 }
> db.m.insert({_id: NumberLong(10000000000000006)})
> db.m.insert({_id: NumberLong(10000000000000007)})
> db.m.insert({_id: NumberLong(10000000000000008)})
E11000 duplicate key error index: t.m.$_id_  dup key: { : 10000000000000008 }
> db.m.insert({_id: NumberLong(10000000000000009)})
E11000 duplicate key error index: t.m.$_id_  dup key: { : 10000000000000008 }

因此,可以使用存储大小小于ObjectId的数字,但要小心。

 类似资料:
  • 问题内容: 我有如下代码: 当我这样做时,Findbugs总是报告错误。 问题答案: 如果您要手动连接,我会使用, 但是,如果您要迭代和串联,我建议,

  • 问题内容: 为什么Catch(Exception)一个坏主意? 问题答案: 因为当你捕获异常时,你应该正确处理它。而且,你不能期望在代码中处理所有类型的异常。同样,当你捕获所有异常时,你可能会得到一个无法处理的异常,并阻止堆栈中位于较高位置的代码正确处理它。 一般原则是捕获可能的最特定类型。

  • 问题内容: 似乎我在某处听到/读到了a的内部禁忌。并不是说它不起作用,只是基于它们的显示类型,关于它们的兼容性不佳。找不到任何证据来支持我的预感,所以我可能完全错了。 问题答案: 使用实例a 并不比使用表进行布局的任何其他方式差。(尽管有些人从不使用表格进行布局,而我恰好是其中之一。) 如果您使用的,你会得到但在一种情况,它可能是很难预测的因素将如何调整大小。div的默认值是从其父对象确定其宽度,

  • 我有两个微服务,一个配置为OAuth2服务器-A,另一个配置为OAuth2客户端-B。我想在这两个微服务之间共享我的自定义用户。当用户使用A对自己进行身份验证时,我创建了UserDetails的自定义实现,我想保护B中的一些资源。因此,我配置了与A相同的资源服务器。我希望我可以使用主体在A和B之间共享UserDetails的自定义实现。我可以从A中的主体获取自定义用户,但在B中,主体仅由字符串(用

  • 问题内容: 我在阅读$ _SESSION [‘username’]进入SQL查询之前是否需要转义? 它说:“无论源如何,都需要对传递给sql查询的每个字符串进行转义”。现在我知道类似这样的事情是非常基本的。Google搜索显示超过20,000个结果。仅Stackoverflow就有20页的结果,但是没有人实际解释转义字符串是什么或如何转义。只是假设。你能帮助我吗?我想学习,因为我一如既往地使用PH

  • 问题内容: 我必须使用字典中的值格式化字符串,但是该字符串已经包含大括号。例如: 但是,当然会导致KeyErro。 有没有办法使用不同的符号来使用? 这不是我如何在python字符串中打印文字大括号字符并在其上使用.format的重复项?因为我需要保持大括号不变,并为使用不同的定界符。 问题答案: 语境 python 2.7 允许自定义占位符语法的替代方法 问题 我们要在Python str.fo