猫鼬在 populate() 方法后返回空数组
Mongoose returning empty array after populate() method
过去 3-4 小时我一直在用头撞墙,并在 Whosebug 上查看了无数文章,但无法得到正确填充数组的响应。将 Express.js 与 Typescript、MongoDB 和猫鼬一起使用。问题是当我收到所有订单的响应时,我的 orderedlines 数组是空的,即使我可以检查并看到 MongoDB atlas 中的 ID。这是实际响应:
[
{
"orderedlines": [],
"_id": "6251c61f7385c349f88fe95a",
"userId": {
"favourites": [
"623b39e684b9baf1109053f8",
"623b3afada0e7828602c78df",
"623b3b49da0e7828602c78e7",
"623b39ba84b9baf1109053f7",
"623b3b59da0e7828602c78e9"
],
"_id": "62326179b9c85d3fc833d686",
"orders": [],
"email": "testche_emailche@gmail.com",
"username": "stef1222",
"password": "be5Y/IoyrcJHH3ud6Mn/I.8PfBm2JrEKHwYRd8cQwUaAdz.YkKSMa",
"firstName": "Stefan",
"lastName": "Georgiev",
"image": "https://res.cloudinary.com/dtggdx3hc/image/upload/v1648046254/deqr4chfysogoppafdug.png",
"isAdmin": false,
"hasWriteAccess": false,
"__v": 0
},
"totalPrice": 121.99,
"__v": 0
}
]
如上所示,我的 userId 已成功填充其所有属性,但 orderedlines 无法填充,它作为空数组返回。如果我删除 .populate() 它 returns 带有 ids
的对象数组
我假设出现问题的 orderServices 中的 findOrdersForUserId 函数
const findOrdersForUserId = async (
userId: string
): Promise<OrderDocument[]> => {
const ordersToReturn = await Order.find({ userId: userId })
.sort({ _id: 1 })
.populate('userId')
.populate({path:'orderedlines', model:OrderLine})
return ordersToReturn
}
这是我的订单模型:
import mongoose, { Document } from 'mongoose'
export type OrderLine = {
orderlineId: string
}
export type OrderDocument = Document & {
userId: string
orderedlines: OrderLine[]
totalPrice: number
}
const orderSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
totalPrice: Number,
orderedlines: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'OrderLine',
},
],
})
export default mongoose.model<OrderDocument>('Order', orderSchema, 'orders')
我的 OrderLine 模型:
import mongoose, { Document } from 'mongoose'
export type OrderLineDocument = Document & {
productId: string
userId: string
quantity: number
price: number
}
const orderLineSchema = new mongoose.Schema({
quantity: { type: Number, default: 1 },
price: Number,
productId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true,
},
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
})
export default mongoose.model<OrderLineDocument>('OrderLine', orderLineSchema, 'orderlines')
Mongoose version used: mongoose@5.13.10
Node version: v16.13.0
Mongo Shell version: v5.0.6
Express version: express@4.17.1
我会列出一些我尝试解决问题但没有成功的文章:
- Mongoose populate() returning empty array
- Mongoose populate does not populate array
- Mongoose populate not populating an array and always returns an empty array
编辑:所有代码都是来自设置为私有的回购的分支的一部分。我不确定如何将 access/link 分享到分支以便更好地预览代码。如果您想查看其他内容或代码的更具体部分,请赐教。
您这样定义 OrderLine
:
export type OrderLine = {
orderlineId: string
}
然后,您将 orderedlines
指定为 OrderLine
:
的数组
orderedlines: OrderLine[]
在您的用例中,orderedlines
是 ObjectId
的数组,而不是嵌套 属性 orderlineId
的对象数组。 TypeScript 可能会在定义模型时进行某种转换。
尝试将 orderedlines
更改为 ObjectId
的数组,然后再试一次?
回答我自己的问题,因为我为此苦苦挣扎并希望帮助未来的人阅读这个问题。
首先,真正重要的问题可能是您是否没有指定 collection 名称。为了指定一个 collection 名称,在您的模型创建中添加第三个参数,如下所示:
export default mongoose.model<OrderLineDocument>('OrderLine',orderLineSchema,'orderLines')
在第三个参数之前,mongoose 创建了一个 collection 名称,其中包含 lower-cased 多元化 模型名称 - orderlines。但是当我试图填充我的回复时,我指的是带有大写字母 L 的 orderLines。所以请注意,请始终指定您的 collection 名称 或 检查您的 collection 名称在你的 MongoDB Shell/ MongoDB Atlas.
其次。始终检查您要填充的 array/object _id 是否 正确 _id 存在于您的 database 中。如果它们是 non-existent 或错误,则响应将包含空数组甚至 return 错误。
例如,当错误发生时我在一开始就添加了这个,但是那些_id不存在(我之前删除了它们但忘记了)首先在我的orderLines collection中(你仍然可以如果它们是正确的 _id 结构,请添加不存在的 _id,因此请注意)
POST http://localhost:5000/api/v1/orders/62326179b9c85d3fc833d686
Content-Type: application/json
{
"orderedlines":[
{"_id": "6251be4d4186c34788e4f034"},
{"_id": "6251be494186c34788e4f030"}
],
"totalPrice":"121.99"
}
第三。如果您使用的是 TypeScript,则可以使用三种方法:
- 使用你自己的类型
export type OrderLine = {
_id: string
}
export type OrderDocument = Document & {
userId: string
orderedlines: OrderLine[],
totalPrice: number
}
- 表示这将是一个字符串数组
export type OrderDocument = Document & {
userId: string
orderedlines: string[],
totalPrice: number
}
- ObjectId 数组
export type OrderDocument = Document & {
userId: string
orderedlines: mongoose.Schema.Types.ObjectId[]
totalPrice: number
}
在考虑了以上三点之后,最终对我有用的是这种方法:
const findOrdersForUserId = async (
userId: string
): Promise<OrderDocument[]> => {
const ordersToReturn = await Order.find({ userId: userId })
.sort({ _id: 1 })
.populate('userId')
.populate({
path: 'orderedlines',
populate: { path: 'productId', model: 'Product' },
})
return ordersToReturn
}
这是我得到的响应的部分,只是为了展示 orderedline、productId 和 userId 都被正确填充了
{
"quantity": 4, //part of a single orderedline object
"_id": "6251be494186c34788e4f030", //part of a single orderedline object
"productId": { // beginning of populated productId
"_id": "623b3b24da0e7828602c78e3",
"name": "AMY SS14R - TRICKSTER",
"image": "https://res.cloudinary.com/dtggdx3hc/image/upload/v1648048425/amy-deluxe-stick-steel-r-ss09r10_1000x1000_bfngtl.jpg",
"price": 1299,
"__v": 0
}, // end of populated productId
"price": 2.99, //part of a single orderedline object
"__v": 0 //part of a single orderedline object
}
], // end of the orderedline array of objects
"_id": "6252bfa8dd00081d7c273e4d", // _id of the order
"userId": { //beginning of populated userId
"favourites": [
"623b39e684b9baf1109053f8",
"623b3afada0e7828602c78df",
"623b3b49da0e7828602c78e7",
"623b39ba84b9baf1109053f7",
"623b3b59da0e7828602c78e9"
],
过去 3-4 小时我一直在用头撞墙,并在 Whosebug 上查看了无数文章,但无法得到正确填充数组的响应。将 Express.js 与 Typescript、MongoDB 和猫鼬一起使用。问题是当我收到所有订单的响应时,我的 orderedlines 数组是空的,即使我可以检查并看到 MongoDB atlas 中的 ID。这是实际响应:
[
{
"orderedlines": [],
"_id": "6251c61f7385c349f88fe95a",
"userId": {
"favourites": [
"623b39e684b9baf1109053f8",
"623b3afada0e7828602c78df",
"623b3b49da0e7828602c78e7",
"623b39ba84b9baf1109053f7",
"623b3b59da0e7828602c78e9"
],
"_id": "62326179b9c85d3fc833d686",
"orders": [],
"email": "testche_emailche@gmail.com",
"username": "stef1222",
"password": "be5Y/IoyrcJHH3ud6Mn/I.8PfBm2JrEKHwYRd8cQwUaAdz.YkKSMa",
"firstName": "Stefan",
"lastName": "Georgiev",
"image": "https://res.cloudinary.com/dtggdx3hc/image/upload/v1648046254/deqr4chfysogoppafdug.png",
"isAdmin": false,
"hasWriteAccess": false,
"__v": 0
},
"totalPrice": 121.99,
"__v": 0
}
]
如上所示,我的 userId 已成功填充其所有属性,但 orderedlines 无法填充,它作为空数组返回。如果我删除 .populate() 它 returns 带有 ids
的对象数组我假设出现问题的 orderServices 中的 findOrdersForUserId 函数
const findOrdersForUserId = async (
userId: string
): Promise<OrderDocument[]> => {
const ordersToReturn = await Order.find({ userId: userId })
.sort({ _id: 1 })
.populate('userId')
.populate({path:'orderedlines', model:OrderLine})
return ordersToReturn
}
这是我的订单模型:
import mongoose, { Document } from 'mongoose'
export type OrderLine = {
orderlineId: string
}
export type OrderDocument = Document & {
userId: string
orderedlines: OrderLine[]
totalPrice: number
}
const orderSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
totalPrice: Number,
orderedlines: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'OrderLine',
},
],
})
export default mongoose.model<OrderDocument>('Order', orderSchema, 'orders')
我的 OrderLine 模型:
import mongoose, { Document } from 'mongoose'
export type OrderLineDocument = Document & {
productId: string
userId: string
quantity: number
price: number
}
const orderLineSchema = new mongoose.Schema({
quantity: { type: Number, default: 1 },
price: Number,
productId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true,
},
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
})
export default mongoose.model<OrderLineDocument>('OrderLine', orderLineSchema, 'orderlines')
Mongoose version used: mongoose@5.13.10
Node version: v16.13.0
Mongo Shell version: v5.0.6
Express version: express@4.17.1
我会列出一些我尝试解决问题但没有成功的文章:
- Mongoose populate() returning empty array
- Mongoose populate does not populate array
- Mongoose populate not populating an array and always returns an empty array
编辑:所有代码都是来自设置为私有的回购的分支的一部分。我不确定如何将 access/link 分享到分支以便更好地预览代码。如果您想查看其他内容或代码的更具体部分,请赐教。
您这样定义 OrderLine
:
export type OrderLine = {
orderlineId: string
}
然后,您将 orderedlines
指定为 OrderLine
:
orderedlines: OrderLine[]
在您的用例中,orderedlines
是 ObjectId
的数组,而不是嵌套 属性 orderlineId
的对象数组。 TypeScript 可能会在定义模型时进行某种转换。
尝试将 orderedlines
更改为 ObjectId
的数组,然后再试一次?
回答我自己的问题,因为我为此苦苦挣扎并希望帮助未来的人阅读这个问题。 首先,真正重要的问题可能是您是否没有指定 collection 名称。为了指定一个 collection 名称,在您的模型创建中添加第三个参数,如下所示:
export default mongoose.model<OrderLineDocument>('OrderLine',orderLineSchema,'orderLines')
在第三个参数之前,mongoose 创建了一个 collection 名称,其中包含 lower-cased 多元化 模型名称 - orderlines。但是当我试图填充我的回复时,我指的是带有大写字母 L 的 orderLines。所以请注意,请始终指定您的 collection 名称 或 检查您的 collection 名称在你的 MongoDB Shell/ MongoDB Atlas.
其次。始终检查您要填充的 array/object _id 是否 正确 _id 存在于您的 database 中。如果它们是 non-existent 或错误,则响应将包含空数组甚至 return 错误。
例如,当错误发生时我在一开始就添加了这个,但是那些_id不存在(我之前删除了它们但忘记了)首先在我的orderLines collection中(你仍然可以如果它们是正确的 _id 结构,请添加不存在的 _id,因此请注意)
POST http://localhost:5000/api/v1/orders/62326179b9c85d3fc833d686
Content-Type: application/json
{
"orderedlines":[
{"_id": "6251be4d4186c34788e4f034"},
{"_id": "6251be494186c34788e4f030"}
],
"totalPrice":"121.99"
}
第三。如果您使用的是 TypeScript,则可以使用三种方法:
- 使用你自己的类型
export type OrderLine = {
_id: string
}
export type OrderDocument = Document & {
userId: string
orderedlines: OrderLine[],
totalPrice: number
}
- 表示这将是一个字符串数组
export type OrderDocument = Document & {
userId: string
orderedlines: string[],
totalPrice: number
}
- ObjectId 数组
export type OrderDocument = Document & {
userId: string
orderedlines: mongoose.Schema.Types.ObjectId[]
totalPrice: number
}
在考虑了以上三点之后,最终对我有用的是这种方法:
const findOrdersForUserId = async (
userId: string
): Promise<OrderDocument[]> => {
const ordersToReturn = await Order.find({ userId: userId })
.sort({ _id: 1 })
.populate('userId')
.populate({
path: 'orderedlines',
populate: { path: 'productId', model: 'Product' },
})
return ordersToReturn
}
这是我得到的响应的部分,只是为了展示 orderedline、productId 和 userId 都被正确填充了
{
"quantity": 4, //part of a single orderedline object
"_id": "6251be494186c34788e4f030", //part of a single orderedline object
"productId": { // beginning of populated productId
"_id": "623b3b24da0e7828602c78e3",
"name": "AMY SS14R - TRICKSTER",
"image": "https://res.cloudinary.com/dtggdx3hc/image/upload/v1648048425/amy-deluxe-stick-steel-r-ss09r10_1000x1000_bfngtl.jpg",
"price": 1299,
"__v": 0
}, // end of populated productId
"price": 2.99, //part of a single orderedline object
"__v": 0 //part of a single orderedline object
}
], // end of the orderedline array of objects
"_id": "6252bfa8dd00081d7c273e4d", // _id of the order
"userId": { //beginning of populated userId
"favourites": [
"623b39e684b9baf1109053f8",
"623b3afada0e7828602c78df",
"623b3b49da0e7828602c78e7",
"623b39ba84b9baf1109053f7",
"623b3b59da0e7828602c78e9"
],