处理Mongoose虚拟属性中的异步操作

huangapple go评论69阅读模式
英文:

Handling async operation in mongoose virtual property

问题

我在用户模式上创建了一个名为debt的虚拟属性。

debt属性用于返回从Bill模型中的每个用户的总债务的总和聚合。

但虚拟字段debt一直返回Promise { }

这是我的代码示例:

userSchema.virtual('debt').get(async function () {
    const bills = await this.model('Bill').aggregate([
        {
            $match: {
                $and: [{ 'user._id': this._id }, { balance: { $gt: 0 } }]
            }
        },
        {
            $group: { _id: null, total: { $sum: "$balance" } }
        }
    ]);
    console.log(bills) // [{_id: null, total: theSummedValue }]
    return bills[0].total; // Promise { <pending> }
});

如何返回theSummedValue

英文:

I created a virtual property on the users schema called debt

the debt property is to return the sum aggregate of each user total debt from the Bill model

But the virtual field debt keeps returning Promise { <pending> }

Here is my code sample:

userSchema.virtual(&#39;debt&#39;).get(async function () {
    const bills = await this.model(&#39;Bill&#39;).aggregate([
        {
            $match: {
                $and: [{ &#39;user._id&#39;: this._id }, { balance: { $gt: 0 } }]
            }
        },
        {
            $group: { _id: null, total: { $sum: &quot;$balance&quot; } }
        }
    ]);
    console.log(bills) // [{_id: null, total: theSummedValue }]
    return bills[0].total; // Promise { &lt;pending&gt; }
});

how can I return theSummedValue ??

答案1

得分: 1

请查看 issue#1894issue#5762

virtuals 只是获取器/设置器,假定是同步的。

你可以添加一个自定义的 实例方法 代替。

例如("mongoose": "^7.2.1")

import mongoose from 'mongoose';
import { config } from '../../config';

mongoose.set('debug', true);

const userSchema = new mongoose.Schema({
	name: String,
});
userSchema.method('dept', async function () {
	console.log(this);
	// @ts-ignore
	const result = await mongoose.model('bill').aggregate([
		{
			$match: {
				$and: [{ 'user._id': this._id }, { balance: { $gt: 0 } }],
			},
		},
		{
			$group: { _id: null, total: { $sum: '$balance' } },
		},
	]);
	return result[0].total;
});
const User = mongoose.model('user', userSchema);

const billSchema = new mongoose.Schema({
	balance: Number,
	user: userSchema,
});
const Bill = mongoose.model('bill', billSchema);

(async function main() {
	try {
		await mongoose.connect(config.MONGODB_URI);
		await Promise.all([User, Bill].map((m) => m.collection.drop()));
		// seed
		const [user1, user2] = await User.create([{ name: 'Nick' }, { name: 'Jack' }]);
		await Bill.create([
			{ balance: 100, user: user1 },
			{ balance: 200, user: user1 },
			{ balance: 0, user: user1 },
			{ balance: 50, user: user2 },
		]);
		//@ts-ignore
		const dept = await user1.dept();
		console.log("Nick's dept: ", dept);
	} catch (error) {
		console.error(error);
	} finally {
		await mongoose.connection.close();
	}
})();

输出:

Mongoose: users.drop()
Mongoose: bills.drop()
Mongoose: users.insertOne({ name: 'Nick', _id: ObjectId("6498f33d24d77a71b4976083"), __v: 0 }, {})
Mongoose: users.insertOne({ name: 'Jack', _id: ObjectId("6498f33d24d77a71b4976084"), __v: 0 }, {})
Mongoose: bills.insertOne({ balance: 100, user: { name: 'Nick', _id: ObjectId("6498f33d24d77a71b4976083"), __v: 0 }, _id: ObjectId("6498f33d24d77a71b4976087"), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 200, user: { name: 'Nick', _id: ObjectId("6498f33d24d77a71b4976083"), __v: 0 }, _id: ObjectId("6498f33d24d77a71b4976089"), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 0, user: { name: 'Nick', _id: ObjectId("6498f33d24d77a71b4976083"), __v: 0 }, _id: ObjectId("6498f33d24d77a71b497608b"), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 50, user: { name: 'Jack', _id: ObjectId("6498f33d24d77a71b4976084"), __v: 0 }, _id: ObjectId("6498f33d24d77a71b497608d"), __v: 0}, {})
{ name: 'Nick', _id: new ObjectId("6498f33d24d77a71b4976083"), __v: 0 }
Mongoose: bills.aggregate([ { '$match': { '$and': [ { 'user._id': new ObjectId("6498f33d24d77a71b4976083") }, { balance: { '$gt': 0 } } ] } }, { '$group': { _id: null, total: { '$sum': '$balance' } } }], {})
Nick's dept:  300
英文:

See issue#1894 and issue#5762

> virtuals are just getters/setters, which are assumed to be synchronous

You can add a custom instance method instead.

E.g.("mongoose": "^7.2.1")

import mongoose from &#39;mongoose&#39;;
import { config } from &#39;../../config&#39;;

mongoose.set(&#39;debug&#39;, true);

const userSchema = new mongoose.Schema({
	name: String,
});
userSchema.method(&#39;dept&#39;, async function () {
	console.log(this);
	// @ts-ignore
	const result = await mongoose.model(&#39;bill&#39;).aggregate([
		{
			$match: {
				$and: [{ &#39;user._id&#39;: this._id }, { balance: { $gt: 0 } }],
			},
		},
		{
			$group: { _id: null, total: { $sum: &#39;$balance&#39; } },
		},
	]);
	return result[0].total;
});
const User = mongoose.model(&#39;user&#39;, userSchema);

const billSchema = new mongoose.Schema({
	balance: Number,
	user: userSchema,
});
const Bill = mongoose.model(&#39;bill&#39;, billSchema);

(async function main() {
	try {
		await mongoose.connect(config.MONGODB_URI);
		await Promise.all([User, Bill].map((m) =&gt; m.collection.drop()));
		// seed
		const [user1, user2] = await User.create([{ name: &#39;Nick&#39; }, { name: &#39;Jack&#39; }]);
		await Bill.create([
			{ balance: 100, user: user1 },
			{ balance: 200, user: user1 },
			{ balance: 0, user: user1 },
			{ balance: 50, user: user2 },
		]);
		//@ts-ignore
		const dept = await user1.dept();
		console.log(&quot;Nick&#39;s dept: &quot;, dept);
	} catch (error) {
		console.error(error);
	} finally {
		await mongoose.connection.close();
	}
})();

Output:

Mongoose: users.drop()
Mongoose: bills.drop()
Mongoose: users.insertOne({ name: &#39;Nick&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976083&quot;), __v: 0 }, {})
Mongoose: users.insertOne({ name: &#39;Jack&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976084&quot;), __v: 0 }, {})
Mongoose: bills.insertOne({ balance: 100, user: { name: &#39;Nick&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976083&quot;), __v: 0 }, _id: ObjectId(&quot;6498f33d24d77a71b4976087&quot;), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 200, user: { name: &#39;Nick&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976083&quot;), __v: 0 }, _id: ObjectId(&quot;6498f33d24d77a71b4976089&quot;), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 0, user: { name: &#39;Nick&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976083&quot;), __v: 0 }, _id: ObjectId(&quot;6498f33d24d77a71b497608b&quot;), __v: 0}, {})
Mongoose: bills.insertOne({ balance: 50, user: { name: &#39;Jack&#39;, _id: ObjectId(&quot;6498f33d24d77a71b4976084&quot;), __v: 0 }, _id: ObjectId(&quot;6498f33d24d77a71b497608d&quot;), __v: 0}, {})
{ name: &#39;Nick&#39;, _id: new ObjectId(&quot;6498f33d24d77a71b4976083&quot;), __v: 0 }
Mongoose: bills.aggregate([ { &#39;$match&#39;: { &#39;$and&#39;: [ { &#39;user._id&#39;: new ObjectId(&quot;6498f33d24d77a71b4976083&quot;) }, { balance: { &#39;$gt&#39;: 0 } } ] } }, { &#39;$group&#39;: { _id: null, total: { &#39;$sum&#39;: &#39;$balance&#39; } } }], {})
Nick&#39;s dept:  300

huangapple
  • 本文由 发表于 2023年6月25日 21:22:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定