使用正则表达式对MongoDB中的ObjectId进行查询

11

能否执行类似以下的查询:

db.artigo.find( { _id : ObjectId('520a504a3004bc615fcfcf16') } )

但是在ObjectId上使用正则表达式?

例如,获取包含指定位置上的“004”的_ids。

附注:原因是基于某些字段(即_id)实现短链接服务。我正在尝试创建一个隐式的“短链接”服务,而不是显式的(使用为此目的生成的字段)。


Mongo _id 是 objectId 而不是字符串,请查看此链接: https://dev59.com/iGEi5IYBdhLWcg3wwecN - Neo-coder
5个回答

6

ObjectId不是字符串,而是在MongoDB中的一种特殊类型。您不能使用正则表达式运算符对包含ObjectId的字段进行查询。

_id不一定是ObjectId,因此我建议您提供自己的唯一字符串作为_id,然后可以使用正则表达式进行查询。

示例:

let userId = 'bf44fa';

const result = await Users.aggregate([
  {
    $addFields: {
      tempUserId: { $toString: '$_id' },
    }
  },
  {
    $match: {
      tempUserId: { $regex: userId, $options: "i" }
    }
  }
]).exec();

现在我们可以通过聚合操作,按照您的意愿,使用_id的最后6位数字或前6位数字来查找。


5
  • ObjectId不是普通的字符串,而是MongoDB中的特殊类型。你不能使用正则表达式操作符对包含ObjectId的字段进行查询。
  • 但是... _id不一定需要是ObjectId,所以我建议您提供自己的唯一字符串作为_id,然后可以使用正则表达式查询。

你可以通过将字符串赋给 _id 来避免额外的字段。mongoDB 可以为你生成这个。 - nickmilon
查询应该类似于Brian建议的样子: db.artigo.find( { _id : { $regex: any_valid_js_regex_exp } } ) 但是它只适用于在_id字段中存储字符串的情况。 您可以在mongo中使用x=new ObjectId()生成一个ObjectId,然后在将文档保存到db之前将其转换为字符串x.toString()。 请注意,除非您从字符串的开头查找('^xxxxx'),否则mongoDB中的正则表达式查询速度较慢。 - nickmilon
但是我有数百万个文档没有以那种方式保存。 - Luís Soares
那么,我不认为使用正则表达式有解决方案 :-( - nickmilon
你有没有任何替代方案可以使ObjectId变短(压缩它)?我的意思是...那是一个24个字符的16进制数....我想使用[a-zA-Z-09]来压缩它。 - Luís Soares
显示剩余2条评论

1
我认为这是mongodb缺乏的领域之一;而且mongodb团队似乎不会支持这个功能,正如这个(https://jira.mongodb.org/browse/SERVER-1146) jira问题所示。 争论似乎是使用我们自己的字符串格式的id,但在大型系统中,例如亚马逊的订单号,objectId在处理大量交易时是有意义的。 我提出的解决方案如下: 我创建了另一个列,复制了我的_id字段的前六位,并且是字符串类型的。我选择我的_id字段的前六位的原因是:一是为了节省空间和紧凑性,二是最终我需要一个正则表达式来进行搜索,这符合我的需求。

0
你可以像这里提到的那样使用$where
.find({"$where": "/004/.test(this._id.str)"})

-4
这是你需要的内容:

db.artigo.find( { _id : { $regex: '004' } } )


@LuísSoares:这个语法是正确的,所以我不知道为什么你的匹配不上。这是文档链接:http://docs.mongodb.org/manual/reference/operator/query/regex/ - Brian Stephens
问题在于 _id 不是一个字符串。如屏幕截图所示,它是一个 ObjectId。 - Luís Soares
@LuísSoares:啊,现在我明白你的问题了。ObjectId有一个“str”属性,可以返回十六进制字符串。你能否对其执行$regex匹配? - Brian Stephens
不,你也不能这样做。只有在从数据库中检索到ObjectId后,ObjectId.toString()才能将其转换为字符串。 - nickmilon
我不确定为什么有人标记了这个……可能只是代码吧?以防万一,如果您更新它,请尝试在代码块之外添加更多内容。 - Nathan Tuggy

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