#node.js #mongodb #mongoose
Вопрос:
Итак, в основном у меня есть эти данные
{
company: {
subscriptions: [
{
"name": "test1",
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
},
{
"name": "test2",
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
},
{
"services": {
"1": {
"createdAt": ISODate("2021-10-19T06:40:33.583Z"),
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
}
},
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
}
]
}
}
В настоящее время я не знаю, как эти данные вставляются в коллекцию.
Странные данные вот эти.
{
"services": {
"1": {
"createdAt": ISODate("2021-10-19T06:40:33.583Z"),
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
}
},
"updatedAt": ISODate("2021-10-19T06:40:33.583Z")
}
Как я могу использовать mongodb $pull, чтобы удалить этот внутренний массив подписок?
Ответ №1:
Запрос 1
- $pull, если у участника нет поля с именем name, оно удаляется
db.collection.updateMany({},
{
$pull: {
"company.subscriptions": {
name: {
"$exists": false
}
}
}
})
Запрос 2
- альтернативный способ с трубопроводом
- это удаляет элемент массива, если в нем нет поля
name
(или имя равно false/null). - службы, которые вы не хотите удалять, не имеют имени, поэтому они будут отфильтрованы
для обновления конвейера требуется MongoDB >= 4.2
db.collection.updateMany({},
[
{
"$set": {
"company.subscriptions": {
"$filter": {
"input": "$company.subscriptions",
"cond": "$this.name"
}
}
}
}
])
Если ваш метод updateMany не принимает конвейер, вы можете запустить его как команду as
db.runCommand(
{
update: "yourCollection",
updates: [
{
q: { },
u: [
{
"$set": {
"company.subscriptions": {
"$filter": {
"input": "$company.subscriptions",
"cond": "$this.name"
}
}}}
],
multi: true
}
],
ordered: false
}
)
Комментарии:
1. Я получил эту ошибку
Invalid query: Line 1: Expected '(' instead of 'M'
, если используюupdateMany
2. вы могли бы сделать это также с помощью фильтров массива и
$pull
. Вот руководство , но самое важное-это ссылка , в которой есть все типы операторов с примерами3. Большое вам спасибо за ссылки и ваши ответы
4. этот код работает в оболочке, в nodejs, возможно, его небольшая разница, в способе вызова, я ищу его
5. Я уже нашел решение, большое вам спасибо
Ответ №2:
Основываясь на ответе @Takis_, я нашел решение. Вот что я сделал.
const cursor = await Company.find({
$and: [
{
"subscriptions": { $exists: true, $ne: [] }
}
]
}).cursor();
await cursor.eachAsync(async company => {
let isUpdate = false;
const found = find(company.subscriptions, subscription => subscription.name === undefined);
if (!found) return
try {
const res = await Company.updateOne(
{
"_id": mongoose.Types.ObjectId(company._id),
},
{
$pull: { subscriptions: { name: { $exists: false } } }
}
);
} catch(err) {
log(`ERROR removing subscription entry for company ${company.name} - ${company._id}`);
}
})
Хотя у @Takis есть правильный ответ, этот со своей стороны работает на меня