如何直接从mongodb查询返回原始JSON?

cpjpxq1n  于 2022-12-03  发布在  Go
关注(0)|答案(2)|浏览(294)

在MongoDB中(使用mongosh或命令行mongo cli),您可以查询文档,例如使用db.mycollection.find({"something":true})并获得以下结果:

{
"someDate": ISODate("2022-10-24T17:21:44.980Z"),
"something": true,
"hello": "world"
}

然而,这个结果不是有效的JSON(由于ISODate)。我如何改变上面的查询,使MongoDB返回规范的(有效的)JSON?
我正在寻找一种递归和通用的方法来实现这一点,即使是对于深度嵌套的文档。

mf98qq94

mf98qq941#

现有的答案有很多,我先澄清几个:

使用聚合生成JSON格式的输出:Playground

db.collection.aggregate([
  {
    $match: {
      something: true
    }
  },
  {
    $project: {
      _id: 1,
      someDate: {
        $dateToString: {
          format: "%Y-%m-%dT%H:%M:%S:%LZ",
          date: "$someDate"
        }
      },
      something: 1,
      hello: 1
    }
  }
])

在应用程序中循环查询:(例如,node.js)

db.mycollection.find({"something":true}).forEach(function(doc) {   
   doc.someDate = doc.someDate.toISOString() // or even .toJSON()
})

// Or with await

const records = await db.mycollection.find({"something":true}).map(doc => {
  doc.someDate = doc.someDate.toISOString()
  return doc
}).toArray()
sczxawaw

sczxawaw2#

您运行此命令的 * 位置 * 的详细信息非常重要,您能分享这些信息吗?
我 * 猜测 * 您可能是通过(较旧的)mongo实用程序(而不是较新的mongosh)运行此程序。但是确认这一点以及您正在使用的数据库版本都将是有帮助的。为了回答这个问题,我将保留此假设。
但是,此结果不是有效的JSON(由于ISODate)。
数据库本身并不返回包含ISODate的文本。事实上,它根本不返回或“说”JSON。相反,数据库通过"Binary JSON" or BSON for short进行通信。事实上,this page的“* MongoDB使用BSON还是JSON?*”部分特别提到了以下内容:
首先,BSON文档可能包含Date或Binary对象,这些对象在纯JSON中无法原生地表示。
因此,当您看到ISODate()这样的内容时,它是 * 客户端应用程序 *,以更有限的(和基于文本的)类似JSON的表单。重要的是,这通常是为了 * 可读性 * 的目的。2您应该能够以原生方式传递和操作信息(文档)直接在应用程序中由数据库返回,而无需进行任何类型的转换,也不会丢失丰富的类型信息。关于BSON的其他阅读材料是here
回到最初的问题,如果你想让shell打印出一个有效的JSON文档,你可以通过其他的助手来完成。在旧的mongo实用程序中,问题中描述的情况是:

> db.mycollection.findOne({"something": true})
{
    "_id" : 1,
    "someDate" : ISODate("2022-11-30T14:38:37.711Z"),
    "something" : true,
    "hello" : "world"
}

shell本身可以理解和操作ISODate()(以及其他类似的函数),如果出于某种原因确实想删除ISODate()之类的内容,那么可以利用JSON.stringify()功能(为了可读性,重新格式化了行缩进):

> JSON.stringify( db.mycollection.findOne({"something": true}) )
{
  "_id":1,
  "someDate":"2022-11-30T14:38:37.711Z",
  "something":true,
  "hello":"world"
}

较新的mongosh shell在以下方面提供了更多的实用程序:

> EJSON.serialize( db.mycollection.findOne() )
{
  _id: 1,
  someDate: { '$date': '2022-11-30T14:38:37.711Z' },
  something: true,
  hello: 'world'
}

通过这些EJSON函数,mongosh试图在以这种格式打印数据时保留类型信息。注意,在前面的示例中,日期只是表示为字符串,但在这里,shell使用Extended JSON来捕获someDate的类型是Date这一事实。

相关问题