【问题标题】:Mongoose one to one query returning nulllMongoose 一对一查询返回 null
【发布时间】:2017-06-27 10:56:09
【问题描述】:

我正在使用 mongoose 创建两个模型,userchild,它们能够相互关联。在 mongo shell 中,我可以使用 user._id 参数查询子级,并返回一个子级数组,其 admin 属性是指定的用户。此外,在我的节点应用程序中,我可以根据孩子的其他属性(例如name)查询我的孩子数据库。但是,当我执行以下查询时,会返回一个空数组。需要注意的是,user._id 属性是一个确实是管理员的用户的字符串。此外,只需将查询参数更改为name 和相应的值即可成功查询。我错过了什么明显的东西吗?

用户.js

var UserSchema = mongoose.Schema({
    username: {
        type: String,
        index:true
    },
    password: {
        type: String
    },
    email: {
        type: String
    },
    name: {
        type: String
    },
});

Child.js

var childSchema = mongoose.Schema({
  Name:{
    type:String,
    required:true
  },
  Address:{
    type:String,
    required: true
  },
  Admin : { type: Schema.Types.ObjectId, ref: 'User' },
});

查询(返回null):

var ObjectId = require('mongoose').Types.ObjectId;
Child.find({Admin:ObjectId(user._id)},callback);

创建子时使用的参数:

 { "Name" : "First Child", "Address" : "Sample Address", "Admin" : req.user._id }

从 mongo shell 返回的子样本:

{
    "_id" : ObjectId("59519c30c904d23ea2e9f58f"),
    "Name" : "First Child",
    "Address" : "Sample Address",
    "Admin" : ObjectId("594d9e5f9d3b199b781015a3"),
    "__v" : 0
}

示例父级:

{
    "_id" : ObjectId("594d9e5f9d3b199b781015a3"),
    "name" : "User",
    "email" : "user@email.com",
    "username" : "user",
    "password" : "$2a$10$.o9k2yyUMlTpecKVkqWYr.Pg8TMCGIZrexHb3Ce//5ILpC9CDKEeS",
    "__v" : 0
}

【问题讨论】:

  • 可以分享示例文档吗?
  • 你这里似乎有一个基本的误解。您的查询应该只是Child.find({ 'Admin': user._id },callback) 出于某种原因,您认为您需要处理一个名为ObjectId 的属性,但没有这样的属性,因此没有结果。这只是一个“模式类型”来说明存储的类型,而不是实际的文档属性。
  • ObjectId 函数只是将 user._id 转换为正确的类型。我已经看到并尝试过用两种方式编写代码来得到相同的结果@NeilLunn
  • 不是你想的那样。此外,猫鼬已经为您转换了类型,这就是您首先拥有模式的原因。如果您尝试过但没有得到任何结果,则该值不正确。或者可能实际文档的类型错误。我已经为您提供了匹配正确类型的“正确”查询。显示从 mongo shell 中查看的实际文档,这将准确显示数据的类型。
  • 你在 shell 中的集合名称是什么?是“孩子”吗?默认情况下,Mongoose 将集合名称复数,您可以使用显式命名集合的第三个参数覆盖它。即mongoose.model("Child", childSchema, "childcollection"),我在那里明确命名为"childcollection"。除了输入之外,我给出的查询不应该工作没有其他原因。以Child.find({ "Admin": "594d9e5f9d3b199b781015a3" },function(err, result) { if (err) throw err; console.log(result) }) 进行硬编码测试。当然是在你检查集合名称之后。

标签: node.js mongodb mongoose


【解决方案1】:

您似乎对如何处理集合中的属性存在误解,并且不理解 ObjectId 类型实际上已经在您的架构中定义,因此猫鼬会将其“转换”为定义的类型在.find() 操作或能够引用架构的类似操作中为您服务。

因此正确的说法应该是:

Child.find({ "Admin": user._id },callback);

执行此操作时需要注意的事项是:

  • 确保您的输入是有效的并且是您期望的值。最好在遇到问题时通过传递显式值来进行调试:

    Child.find({ "Admin": "594d9e5f9d3b199b781015a3" },function(err, result) {
      if (err) throw err; console.log(result) 
    })
    
  • Mongoose 在确定要寻址的实际集合名称时将给定模型名称“复数”。特别是,如果您已经定义了数据,然后您稍后会为其创建架构,那么您可能需要明确命名该集合,因为它可能与 mongoose 选择的不同:

    mongoose.model("Child", childSchema, "child")
    

在第二种情况下,猫鼬会默认选择"children",因此当命名不同时,实际集合需要显式名称。这里的常见示例是模型 "Person" 实际上会变成 "people"

最后一点,打开“调试”以查看 Mongoose 在将查询/操作发送到 MongoDB 时实际在做什么是一个好主意。

mongoose.set("debug", true)

了解这些事情是您避免未来错误的方法,并且通常可以进一步了解事情的运作方式。

【讨论】:

    【解决方案2】:

    简单的错字。 Schema 将字段定义为Admin,而您使用admin 进行查询。字段名称区分大小写。代码应该是:

    var ObjectId = require('mongoose').Types.ObjectId;
    Child.find({Admin:ObjectId(user._id)},callback);
    

    【讨论】:

    • 这是一个错字,但修复后仍然有相同的结果
    • @PatrickConnors,你能分享一个存储在 db 中的示例文档吗?
    猜你喜欢
    • 2022-10-19
    • 2019-02-07
    • 2020-01-29
    • 2012-02-23
    • 1970-01-01
    • 2019-05-01
    • 2020-05-19
    • 1970-01-01
    • 2019-08-29
    相关资源
    最近更新 更多