英文:
How to sort object inside of array based on createdAt in mongoose?
问题
我正在尝试根据createdAt日期对products数组进行排序。
我的订单模型
const itemSchema = new Schema(
{
productId: { type: Schema.Types.ObjectId, ref: 'Product' },
quantity: {
type: Number,
max: [10, '只能添加10个数量的物品。'],
required: true,
},
price: { type: Number, required: true },
},
{ timestamps: true }
);
const ordersSchema = new Schema({
products: [itemSchema],
userId: { type: Schema.Types.ObjectId, ref: 'User' },
});
我根据一个Stack Overflow的帖子尝试了这个:
const orders = await Order.findOne({ userId: req.userId })
.sort({ 'products.createdAt': -1 })
.slice('products', 10)
.populate({ path: 'products.productId', select: 'images title' });
但它没有返回排序后的数组。
英文:
I am trying to sort the products array based on the createdAt date.
My orders model
const itemSchema = new Schema(
{
productId: { type: Schema.Types.ObjectId, ref: 'Product' },
quantity: {
type: Number,
max: [10, 'Only 10 quantity of one item can be added.'],
required: true,
},
price: { type: Number, required: true },
},
{ timestamps: true }
);
const ordersSchema = new Schema({
products: [itemSchema],
userId: { type: Schema.Types.ObjectId, ref: 'User' },
});
I tried this according to a stack overflow post
const orders = await Order.findOne({ userId: req.userId })
.sort({ 'products.createdAt': -1 })
.slice('products', 10)
.populate({ path: 'products.productId', select: 'images title' });
But it does not return sorted array.
答案1
得分: 2
If you run current version (6.0) of MongoDB, then you can use $sortArray:
db.collection.aggregate([
{
$set: {
products: {
$sortArray: {
input: "$products",
sortBy: { createdAt: 1 }
}
}
}
}
])
英文:
If you run current version (6.0) of MongoDB, then you can use $sortArray:
db.collection.aggregate([
{
$set: {
products: {
$sortArray: {
input: "$products",
sortBy: { createdAt: 1 }
}
}
}
}
])
答案2
得分: 1
db.collection.aggregate([
{
"$unwind": "$products"
},
{
"$sort": {
"products.createdAt": -1
}
},
{
"$group": {
_id: "$_id",
products: {
"$push": "$products"
}
}
}
])
[
{
"_id": ObjectId("5a934e000102030405000000"),
"products": [
{
"createdAt": "2023-07-03",
"productId": "3"
},
{
"createdAt": "2023-07-02",
"productId": "1"
},
{
"createdAt": "2023-07-01",
"productId": "2"
}
]
}
]
Mongoose(v7.3.4) 示例:
import mongoose from 'mongoose';
import util from 'util';
import { config } from '../../config';
mongoose.set('debug', true);
console.log(mongoose.version);
const productSchema = new mongoose.Schema({
title: String,
images: [],
});
const Product = mongoose.model('Product', productSchema);
const itemSchema = new mongoose.Schema(
{
productId: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' },
},
{ timestamps: true },
);
const Item = mongoose.model('Item', itemSchema);
const ordersSchema = new mongoose.Schema({
products: [itemSchema],
});
const Orders = mongoose.model('Orders', ordersSchema);
(async function main() {
try {
await mongoose.connect(config.MONGODB_URI);
await Promise.all([Product, Item, Orders].map((m) => m.collection.drop()));
// 种子数据
const [p1, p2, p3] = await Product.create([
{ title: 'product a', images: ['a', 'b'] },
{ title: 'product b', images: ['c', 'd'] },
{ title: 'product c', images: ['e', 'f'] },
]);
const items = await Item.create([
{ productId: p1, createdAt: new Date(2023, 6, 4) },
{ productId: p3, createdAt: new Date(2023, 6, 3) },
{ productId: p2, createdAt: new Date(2023, 6, 5) },
]);
const [o1] = await Orders.create([{ products: items }]);
// 测试
const r = await Orders.aggregate()
.match({ _id: o1?._id })
.unwind('products')
.lookup({
from: 'products',
localField: 'products.productId',
foreignField: '_id',
as: 'lookup_products',
})
.unwind('lookup_products')
.addFields({ 'products.title': '$lookup_products.title', 'products.images': '$lookup_products.images' })
.sort({ 'products.createdAt': -1 })
.group({ _id: '$_id', products: { $push: '$products' } })
.project({ lookup_products: 0 });
console.log(util.inspect(r, false, null));
} catch (error) {
console.error(error);
} finally {
await mongoose.connection.close();
}
})();
日志:
[
{
_id: new ObjectId("64b4e66fdafc40c3caae9ee5"),
products: [
{
productId: new ObjectId("64b4e66edafc40c3caae9eda"),
_id: new ObjectId("64b4e66fdafc40c3caae9ee1"),
createdAt: 2023-07-04T16:00:00.000Z,
updatedAt: 2023-07-04T16:00:00.000Z,
__v: 0,
title: 'product b',
images: [ 'c', 'd' ]
},
{
productId: new ObjectId("64b4e66edafc40c3caae9ed9"),
_id: new ObjectId("64b4e66fdafc40c3caae9edf"),
createdAt: 2023-07-03T16:00:00.000Z,
updatedAt: 2023-07-03T16:00:00.000Z,
__v: 0,
title: 'product a',
images: [ 'a', 'b' ]
},
{
productId: new ObjectId("64b4e66edafc40c3caae9edb"),
_id: new ObjectId("64b4e66fdafc40c3caae9ee0"),
createdAt: 2023-07-02T16:00:00.000Z,
updatedAt: 2023-07-02T16:00:00.000Z,
__v: 0,
title: 'product c',
images: [ 'e', 'f' ]
}
]
}
]
<details>
<summary>英文:</summary>
```ts
db.collection.aggregate([
{
"$unwind": "$products"
},
{
"$sort": {
"products.createdAt": -1
}
},
{
"$group": {
_id: "$_id",
products: {
"$push": "$products"
}
}
}
])
Input:
[
{
userId: "1",
products: [
{
productId: "1",
createdAt: "2023-07-02"
},
{
productId: "2",
createdAt: "2023-07-01"
},
{
productId: "3",
createdAt: "2023-07-03"
},
]
}
]
Output:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"products": [
{
"createdAt": "2023-07-03",
"productId": "3"
},
{
"createdAt": "2023-07-02",
"productId": "1"
},
{
"createdAt": "2023-07-01",
"productId": "2"
}
]
}
]
Mongoose(v7.3.4) example :
import mongoose from 'mongoose';
import util from 'util';
import { config } from '../../config';
mongoose.set('debug', true);
console.log(mongoose.version);
const productSchema = new mongoose.Schema({
title: String,
images: [],
});
const Product = mongoose.model('Product', productSchema);
const itemSchema = new mongoose.Schema(
{
productId: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' },
},
{ timestamps: true },
);
const Item = mongoose.model('Item', itemSchema);
const ordersSchema = new mongoose.Schema({
products: [itemSchema],
});
const Orders = mongoose.model('Orders', ordersSchema);
(async function main() {
try {
await mongoose.connect(config.MONGODB_URI);
await Promise.all([Product, Item, Orders].map((m) => m.collection.drop()));
// seed
const [p1, p2, p3] = await Product.create([
{ title: 'product a', images: ['a', 'b'] },
{ title: 'product b', images: ['c', 'd'] },
{ title: 'product c', images: ['e', 'f'] },
]);
const items = await Item.create([
{ productId: p1, createdAt: new Date(2023, 6, 4) },
{ productId: p3, createdAt: new Date(2023, 6, 3) },
{ productId: p2, createdAt: new Date(2023, 6, 5) },
]);
const [o1] = await Orders.create([{ products: items }]);
// test
const r = await Orders.aggregate()
.match({ _id: o1?._id })
.unwind('products')
.lookup({
from: 'products',
localField: 'products.productId',
foreignField: '_id',
as: 'lookup_products',
})
.unwind('lookup_products')
.addFields({ 'products.title': '$lookup_products.title', 'products.images': '$lookup_products.images' })
.sort({ 'products.createdAt': -1 })
.group({ _id: '$_id', products: { $push: '$products' } })
.project({ lookup_products: 0 });
console.log(util.inspect(r, false, null));
} catch (error) {
console.error(error);
} finally {
await mongoose.connection.close();
}
})();
Logs:
[
{
_id: new ObjectId("64b4e66fdafc40c3caae9ee5"),
products: [
{
productId: new ObjectId("64b4e66edafc40c3caae9eda"),
_id: new ObjectId("64b4e66fdafc40c3caae9ee1"),
createdAt: 2023-07-04T16:00:00.000Z,
updatedAt: 2023-07-04T16:00:00.000Z,
__v: 0,
title: 'product b',
images: [ 'c', 'd' ]
},
{
productId: new ObjectId("64b4e66edafc40c3caae9ed9"),
_id: new ObjectId("64b4e66fdafc40c3caae9edf"),
createdAt: 2023-07-03T16:00:00.000Z,
updatedAt: 2023-07-03T16:00:00.000Z,
__v: 0,
title: 'product a',
images: [ 'a', 'b' ]
},
{
productId: new ObjectId("64b4e66edafc40c3caae9edb"),
_id: new ObjectId("64b4e66fdafc40c3caae9ee0"),
createdAt: 2023-07-02T16:00:00.000Z,
updatedAt: 2023-07-02T16:00:00.000Z,
__v: 0,
title: 'product c',
images: [ 'e', 'f' ]
}
]
}
]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论