#node.js #mongodb #mongoose #mongodb-query
#node.js #mongodb #mongoose #mongodb-запрос
Вопрос:
Могу ли я вернуть логическую переменную в соответствии с условиями в запросе mongoose? Например, при получении всех уведомлений пользователя я хочу показать, видит ли уведомление пользователь или нет.
У меня есть эта схема:
const notificationSchema = mongoose.Schema({
userid: { type: mongoose.Schema.Types.ObjectId, ref:'User', require: true, unique: false },
time: Number,
type: Number,
seenBy: {type: [String], default: []} // can have very large number of values (user IDs)
}, {__v: false});
Теперь при получении массива уведомлений я хочу получить дополнительное поле seen
, которое является истинным, если конкретный пользователь существует в соответствующем массиве seenBy[] поля.
так что я получаю объект ответа, подобный
1 новое уведомление
[{userid: <someid>, time: ... <other fields> ..., seen: false}]
Спасибо
Комментарии:
1. вы можете использовать
count()
, например, если количество seenBy с условиями равно нулю, возвращает true, иначе возвращает false2. Значит, это уведомление создается одним пользователем, но его могут видеть многие другие пользователи? Это правильно?
3. @PascalLamers верно
Ответ №1:
Вам нужно будет выполнить операцию агрегирования, в которой вы используете $setIsSubset
оператор для двух массивов, т.Е. массивов the [userId]
и seenBy, который возвращает true, когда первый массив является подмножеством второго, в том числе когда первый массив равен второму массиву, и false в противном случае.
Первый массив идентификаторов пользователя должен быть строковым массивом, поскольку вы будете сравнивать массив с другим типом string, поэтому вам нужно преобразовать ObjectId в string с помощью $toString
.
В качестве примера ниже показан запрос:
const userId = '5ffafefe288e7a58ff08226e'; // the user id input variable as a string, could be from req.params.id or req.query.userId etc
const notifications = await Notification.aggregate([
{ '$match': { userid: mongoose.Types.ObjectId(userId) } },
{ '$addFields': {
'seen': {
'$setIsSubset': [
[{ '$toString': '$userid' }],
'$seenBy'
]
}
}}
]);
Комментарии:
1. @chrisdam спасибо за ответ, но могу ли я выполнить ту же функциональность в запросе find() ?
2. @PratikAgarwal Вы не можете добиться того же с помощью find, однако вы можете выполнить преобразование на стороне клиента, а не на сервере
3. какие изменения? Если нет, мне придется выполнить 2 запроса. Это плохо 😔
Ответ №2:
Вы должны попробовать
async func () {
const doesUserExit = await User.exists({ _id: userid });
}
Подробнее model.exists, вернет true или false .
Комментарии:
1. Я использовал это, но мне нужна дополнительная переменная в запросе, поэтому мне не придется запускать цикл, независимо от того, существует он или нет. Мне нужны все уведомления и «замечено: ложь» в тех, где вызываемый идентификатор пользователя отсутствует в массиве seenBy