【问题标题】:JSON.parse fails on ObjectIdJSON.parse 在 ObjectId 上失败
【发布时间】:2019-12-02 05:55:28
【问题描述】:

我正在尝试转换一个字符串以在 mongodb 中使用,但失败了。

    let pipeline = JSON.parse('[{"$match": {"_id": ObjectId("5b5637acbd3e9c2068ef80c3")}]');
    // results in  "SyntaxError: Unexpected token O in JSON at position 20"s

    let pipeline = JSON.parse('[{"$match": {"_id": "5b5637acbd3e9c2068ef80c3"}]');
    let response = await db.collect('<collection_name>').aggregate(pipeline).toArray();
    // returns []  parse works but mongodb doesn't return any rows!

    // This works but its not the solution I am looking for.
    let pipeline = [{"$match": {"_id": ObjectId("5b5637acbd3e9c2068ef80c3")}];
    let response = await db.collect('<collection_name>').aggregate(pipeline).toArray();

我尝试使用 BSON 类型,但没有成功。

我目前的工作是从字符串中删除 ObjectId() 并使用带有 JSON.parse 的 Reviver 函数

    const ObjectId = require('mongodb').ObjectID;

    let convertObjectId = function (key,value){
        if (typeof value === 'string' && value.match(/^[0-9a-fA-F]{24}$/)){
            return ObjectId(value);
        } else {
            return value;
        };
    }

    let pipeline = JSON.parse('[{"$match": {"_id": "5b5637acbd3e9c2068ef80c3"}]',convertObjectId);
    let response = await db.collect('<collection_name>').aggregate(pipeline).toArray();
    // returns one record.

【问题讨论】:

  • [{"$match": {"_id": ObjectId("5b5637acbd3e9c2068ef80c3")}] 不是有效的 json。从here查看它
  • 请问你为什么要解析它。
  • 这个练习的目的是让我可以通过 API / req.body 传递一个 mongodb 管道。我正在编写一个基于浏览器的工具来处理 mongodb 聚合(因为我已经厌倦了 Studio 3T)

标签: node.js json mongodb


【解决方案1】:

很遗憾,[{"$match": {"_id": ObjectId("5b5637acbd3e9c2068ef80c3")}] 不是有效的 JSON。

JSON 中属性的值只能是对象(例如:{})、数组(例如:[])、字符串(例如:"abc")、数字(例如.: 1)、布尔值(例如:true)或 null。在此处查看这些值的示例:https://en.wikipedia.org/wiki/JSON#Example

您可以做的是在解析 JSON 后手动添加 ObjectId()。这意味着_id 的值首先是一个字符串,这是有效的 JSON。

然后,您可以遍历解析的 JSON 以添加 ObjectId(请参阅此处的参考:https://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html):

const ObjectId = require('mongodb').ObjectID;
const pipeline = JSON.parse('[{"$match": {"_id": "5b5637acbd3e9c2068ef80c3"}]');
const pipelineWithObjectId = pipeline.map(query => ({
    $match: {
        ...query.$match,
        _id: ObjectId(query.$match._id)
    }
});
const response = await db.collect('<collection_name>').aggregate(pipelineWithObjectId).toArray();

这应该适用于您提供的示例,但有多个警告:

所有这些原因,就其价值而言,让我认为您最好使用对象而不是字符串进行查询。

【讨论】:

  • 这就是我的 Reviver 功能所做的。这个练习的目的是让我可以通过 API / req.body 传递一个 mongodb 管道。我正在编写一个基于浏览器的工具来处理 mongodb 聚合(因为我已经厌倦了 Studio 3T)
  • 啊!是的,我感同身受。我对 Studio 3T 的感觉很复杂。像我在代码 sn-p 中演示的注入ObjectId 的解决方案对您不起作用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多