在MongoDB中,通过INC值查找文档

6

通过我的网站客户端向后端 Node.js 服务器发送 API 请求,并按 ID 查找特定文档,如下所示:

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

db.collection('users').find({"_id": new ObjectID(req.body._id)})

req.body._id 等于整个ID字符串时,例如 '5d0381ad681a2a3aa1dc5872'

但我更希望只发送 INC (持续增加的值)作为参数:'c5872'

如何基于仅 INC 值找到特定文档? (我假设INC是唯一的)

非常感谢您的任何帮助。


https://dev59.com/CVkT5IYBdhLWcg3wIsMd - Tushar Gupta - curioustushar
嗨,不能保证INC是唯一的。为什么要担心使用ObjectId呢? - Haniel Baez
只是为了保持简单和干净。我们将ID作为URL参数提供给我们的联盟会员,并且我们更喜欢使用5个字符而不是24个。 - mobiman
2个回答

3
您可以将 _id 临时转换为字符串,以便使用正则表达式:
db.users.aggregate([
  {
    $addFields: { id: { $toString: '$_id' } }
  },
  {
    $match: { id: /c5872$/ }
  }
])

更简洁的解决方案是直接使用字符串子串创建字段,而不使用正则表达式:
db.users.aggregate([
  {
    $addFields: { id: { $substr: [{ $toString: '$_id' }, 19, 24] } }
  },
  {
    $match: { id: 'c5872' }
  }
])

https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/ https://docs.mongodb.com/manual/reference/operator/aggregation/substr/


嗨,看起来很干净,但是文档上说:尽可能早地将$match放在聚合管道中。因为$match限制了聚合管道中的文档总数,较早的$match操作可以最小化管道中的处理量。 - Haniel Baez
@HanielBaez 是的,$addFields 操作将在整个集合上执行,但这需要在应用 $match 之前完成。如果集合很大,最好真正在数据库中创建字段,以便在该字段上建立索引,就像您在答案中建议的那样。 - Romain Simon

1
你可以创建一个额外的ID字段和唯一索引来确保索引字段不存储重复值,但请注意,对于五个十六进制字符串,我们有“1,048,576”种可能的组合(16 ^ 5 = 1048576)。
注意:使用正则表达式可能会导致集合扫描。

如果正则表达式以插入符号(^)或左锚点(\A)开头,后面跟着一串简单符号,则该正则表达式是“前缀表达式”。例如,正则表达式 /^abc.*/ 将通过仅匹配以 abc 开头的索引值进行优化。

正则表达式和索引使用

使用6个字符代替5个对我来说是可以的。 - mobiman
MongoDB的_id字段不是已经自动生成并且唯一了吗?您是建议创建一个额外的ID字段以避免集合扫描吗? - mobiman
是的,_id 是唯一的。我说的是,在使用正则表达式时应该小心,它可能会导致集合扫描。 - Haniel Baez
但是,如果MongoDB中没有任何值可以满足查询条件,那么它只会导致集合扫描。但是,在这种情况下,即使我创建了一个额外的ID字段(没有正则表达式),我也有可能进行集合扫描,对吗? - mobiman
嗯...我想我明白你的意思了。通过创建一个额外的ID字段,我们可以在该字段上放置索引。从而避免可能出现的集合扫描。 - mobiman
如果该字段被索引,并且没有任何值能够满足查询条件,最糟糕的情况就是进行索引扫描(也不算太糟糕)。 - Haniel Baez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接