javascript - 使用 Mongoose 和 GraphQL 从填充模型有条件地返回值的最有效方法?
问题描述
我的目标是根据填充后从模型本身检索到的数据有条件地返回模型值。
这是我目前的解决方案:
const bcrypt = require("bcryptjs")
const jwt = require("jsonwebtoken")
const moment = require("moment")
const User = require("../../models/user")
const Post = require("../../models/post")
const { checkAuthorSettings, checkFollowingAuthorSettings } = require('../../shared/utility')
login: async ({ email, password }) => {
try {
const user = await User.findOne({ email }).populate([
{
path: 'posts',
model: 'Post',
populate: [
{
path: 'author',
model: 'User',
},
{
path: 'comments',
model: 'Comment',
populate: {
path: 'author',
model: 'User',
},
},
],
},
{
path: 'following',
model: 'User',
populate: {
path: 'posts',
model: 'Post',
populate: [
{
path: 'author',
model: 'User',
},
{
path: 'comments',
model: 'Comment',
populate: {
path: 'author',
model: 'User',
},
},
],
},
},
{
path: 'favourites',
model: 'Post',
populate: [
{
path: 'author',
model: 'User',
},
{
path: 'comments',
model: 'Comment',
populate: {
path: 'author',
model: 'User',
},
},
],
},
])
if (!user) throw new Error("An Account by that Email was not found!")
if (!password) throw new Error("Please enter your password")
const passIsValid = bcrypt.compareSync( password, user.password )
if (!passIsValid) throw new Error("Incorrect Password")
const token = jwt.sign(
{
_id: user._id,
email: user.email,
},
`${process.env.JWT_SECRET}`,
{ expiresIn: "1h" }
)
user.status = "online"
user.logged_in_at = moment().format()
await user.save()
return {
...user._doc,
token,
token_expiry: 1,
email: user.settings.display_email ? user.email : "",
website: user.settings.display_website ? user.website : "",
password: null,
posts: await checkAuthorSettings(user.posts),
following: await checkFollowingAuthorSettings(user.following),
favourites: await checkAuthorSettings(user.favourites),
info: JSON.stringify(user._doc.info),
geolocation: JSON.stringify(user._doc.geolocation),
settings: JSON.stringify(user._doc.settings),
}
} catch (err) {
throw err
}
},
实用程序.js:
const checkAuthorSettings = array => {
return array.map(post => {
return {
...post._doc,
author: {
...post._doc.author._doc,
email: post._doc.author._doc.settings.display_email ? post._doc.author._doc.email : "",
website: post._doc.author._doc.settings.display_website ? post._doc.author._doc.website : "",
}
}
})
}
const checkFollowingAuthorSettings = array => {
return array.map(followed => {
return {
...followed._doc,
posts: checkAuthorSettings(followed.posts)
}
})
}
exports.checkAuthorSettings = checkAuthorSettings
exports.checkFollowingAuthorSettings = checkFollowingAuthorSettings
我目前正在遍历 User 中的每个数组,我认为这远不是实现这一目标的最有效方法。
有人有比这更好的解决方案吗?
解决方案
可以使用virtuals
,virtuals的实现方式有很多种,如果想email
直接替换字段,可以使用getter
例如
const AuthorSchema = new Schema({
// other fields
email: String,
}, {
toObject: { getters: true }
})
AuthorSchema.path('email').get(function(email) {
return this.get('settings.display_email') ? email : ''
})
然后,当您调用.toObject()
文档时,您将获得一个virtual
值。
推荐阅读
- angular - 在客户端解析器中导入类型时,如何避免使用 Apollo 客户端和“graphql-codegen”的角度项目中的循环依赖?
- c++ - 我该如何处理这样的问题?
- python - 执行 .exe - pyinstaller 时出现错误 No module named 'img2pdf'
- java - RX Java- 使用 java var args 压缩 n 个 Observables
- presto - 设置将使用 INSERT 语句写入的文件数
- tensorflow - TensorFlow GPU 设备“无法获取设备属性”
- dynamics-crm - 如何在 Dynamics 365 手机应用程序上隐藏模型驱动应用程序?
- c# - 将 datagridview 行插入 SQL 表
- python-3.x - pyspark dstream 中的 distinct() 等价物是什么?
- ruby - 试图从包含多个字符串的日志文件中获取数据