【问题标题】:Mongodb Can't Query SubDocument by ID (returns null)Mongodb 无法按 ID 查询子文档(返回 null)
【发布时间】:2019-08-18 12:59:21
【问题描述】:

所以我有这个猫鼬模式:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var CommentSchema = new Schema({
  body: {type: String, required: true, max: 2000},
  created: { type: Date, default: Date.now },
  flags: {type: Number, default: 0},
  lastFlag: {type: Date, default: Date.now()},
  imageBanned: {type: Boolean, default: false},
  fileName: {type: String, default: ""}
}, {
  writeConcern: {
    w: 0,
    j: false,
    wtimeout: 200
  }  
});

var PostSchema = new Schema({
  body: {type: String, required: true, max: 2000},
  created: { type: Date, default: Date.now },
  flags: {type: Number, default: 0},
  lastFlag: {type: Date, default: Date.now()},
  fileName: {type: String, default: ""},
  imageBanned: {type: Boolean, default: false},
  board: {type: String, default: ""},
  comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }]
}, {
  writeConcern: {
    w: 0,
    j: false,
    wtimeout: 200
  }  
});


var Post =  mongoose.model('Post', PostSchema);
var Comment = mongoose.model('Comment', CommentSchema)

module.exports = {Post, Comment}

我正在尝试在 post 的评论数组中查询评论。

这是我正在尝试的端点:

router.post('/flagComment', (req, res, next)=>{
  console.log('inside /flagComment')
  console.log('value of req.body: ', req.body)
  model.Post.findOne({"comments._id": req.body.id}).exec((err, doc)=>{
    if(err){
      console.log('there was an error: ', err)
    }
    console.log('the value of the found doc: ', doc)
    res.json({dummy: 'dummy'})
  })
})

但是,这会给出以下终端输出:

value of req.body:  { id: '5c9bd902bda8d371d5c808dc' }
the value of the found doc:  null

这不正确...我已验证 ID 正确 - 为什么找不到评论文档?

编辑:

我尝试了这个解决方案 (Can't find documents searching by ObjectId using Mongoose),方法是这样设置 objectID:

var ObjectId = require('mongoose').Types.ObjectId; 

router.post('/flagComment', (req, res, next)=>{
  console.log('inside /flagComment')
  console.log('value of req.body: ', req.body)
  console.log('value of objid req id : ',  ObjectId(req.body.id))
  model.Post.find({"comments._id": ObjectId(req.body.id)}).exec((err, doc)=>{
    if(err){
      console.log('there was an error: ', err)
    }
    console.log('the value of the found doc: ', doc)
    res.json({dummy: 'dummy'})
  })
})

我得到以下终端输出:

value of req.body:  { id: '5c9bd902bda8d371d5c808dc' }
value of objid req id :  5c9bd902bda8d371d5c808dc
the value of the found doc:  []

所以,这还不是一个解决方案,尽管它似乎比我的更好。

【问题讨论】:

标签: javascript node.js database mongodb mongoose


【解决方案1】:

无论您认为自己是多少,您都不是在查询 ObjectId。您正在查询编码为十六进制字符串的 ObjectId,这 not 是一回事。正确地进行类型转换,您可能会取得更大的成功。

编辑详细,来自 mongo (JS) REPL shell:

> // Omitting the _id, or generating a new one, are equivalent during insert.
> db.foo.insert({_id: ObjectId()})
WriteResult({ "nInserted" : 1 })

> db.foo.find()  // As expected, we get back our _real_ ObjectId value.
{ "_id" : ObjectId("5c9cfab873724727778c0730") }

> // Can we "insert the record again" using a string version of the ID?
> db.foo.insert({_id: "5c9cfab873724727778c0730"})
WriteResult({ "nInserted" : 1 })  // Sure as heck can! No unique violation!

> db.foo.find()  // Because THESE ARE NOT THE SAME
{ "_id" : ObjectId("5c9cfab873724727778c0730") }
{ "_id" : "5c9cfab873724727778c0730" }

在我们的 IRC 讨论之后,您似乎很难理解答案中的“可搜索词”。在 StackOverflow(或 Google,或 DDG)上搜索“mongoose typecast ObjectId”(不带引号;或只是“mongoose ObjectId”……),您会找到很多答案,因为这是 Mongoose 用户特别常见的问题。

【讨论】:

  • 你能提供一个代码示例吗?我不确定我是否理解。
  • @PeterWeyand 我不是 Mongoose,也不是 JS。答案很明确:在尝试使用该值进行查询之前,将该值类型转换为真实的ObjectId。十六进制编码字符串 != 二进制值,与 base64 编码字符串 != 原始二进制值相同。
  • 好的,感谢您的帮助,但这个答案还不足以让我找到解决方案。谢谢。
  • @PeterWeyand 对于傻笑,我确实使用mongo REPL shell 中的一些代码进行了更新,它是 JS。此代码从使用 _id 上的唯一索引的角度演示了您遇到的确切问题,以证明比较的不相似性和无能/不适当性。给出的答案(“正确typecast”)成立。
【解决方案2】:

先尝试检查填充参考数据,然后查询评论的_id。

*除了comment id之外,还可以从前端获取post id,这样会更容易。

Post.findOne({_id:'postId'})
.populate({
  path  : 'comment',
  match : { _id : 'commentId' }
})
.exec(...);

【讨论】:

  • 谢谢...我的意思是这可行,但是...感觉有点像后门黑客。为什么我不能直接通过 id 查询评论?我认为这样做需要 A) obv。传递另一个 id 和 B)我认为在不需要时搜索 Post 是另一个查询。
  • 如果您检查数据库,mongodb 不会像您搜索“cmets._id”那样将数据保存在评论字段中,它以类似 { "$ref" : "comment" 的格式保存, "$id" : ObjectId("commentid"), "$db" : "dbname" }
  • 我不认为这是正确的。这是帖子的终端输出:{ flags: 0, lastFlag: 2019-03-27T21:00:54.316Z, fileName: '1553720454192&&hotdog.png', imageBanned: false, board: 'nsfw', comments: [ { flags: 0, lastFlag: 2019-03-27T21:01:03.540Z, imageBanned: false, fileName: '1553720463408&&hotdog.png', _id: 5c9be48f0556ec5397cb62a2, body: 'dadf', created: 2019-03-27T21:01:03.540Z, __v: 0 } ], _id: 5c9be4860556ec5397cb62a1, body: 'dog', created: 2019-03-27T21:11:15.575Z, __v: 0 }
  • 如果您的问题已得到解答,请确保接受答案以供进一步参考。
  • 还没有回答-请参考我的cmets,谢谢。
猜你喜欢
  • 2020-01-20
  • 2023-03-30
  • 2022-01-03
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
相关资源
最近更新 更多