Mongoose: возвращает логическую переменную, если запись отсутствует в массиве

#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, иначе возвращает false

2. Значит, это уведомление создается одним пользователем, но его могут видеть многие другие пользователи? Это правильно?

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