【发布时间】:2021-05-03 08:53:53
【问题描述】:
是否可以找出不在数据库中的查询数组元素?
示例:
const query = ['aaa','bbb','ccc']
数据库中的文档:
[{name:'bbb'},{name:'ccc'}]
我想查找不在数据库中的查询数组元素: 返回结果应该是:
['aaa']
除了查询数组中的每个元素(或批次?)之外,我找不到一些快速的方法来做到这一点
谁有更好的方法?谢谢
【问题讨论】:
是否可以找出不在数据库中的查询数组元素?
示例:
const query = ['aaa','bbb','ccc']
数据库中的文档:
[{name:'bbb'},{name:'ccc'}]
我想查找不在数据库中的查询数组元素: 返回结果应该是:
['aaa']
除了查询数组中的每个元素(或批次?)之外,我找不到一些快速的方法来做到这一点
谁有更好的方法?谢谢
【问题讨论】:
查询 -missing- 的东西总是一个更昂贵的操作,也没有“神奇”的查询可以为你做这件事。我推荐使用 Mongo 的 distinct 方法,如下所示:
const queryArr = ['aaa', 'bbb', 'ccc'];
const allNames = await db.collection.distinct('name');
const notInDb = queryArr.filter(e => !allNames.includes(e));
但是,如果您想在 1 db 命令中执行此操作,您可以执行以下操作:
db.collection.aggregate([
{
$group: {
_id: null,
names: {
"$addToSet": "$name"
}
}
},
{
"$replaceRoot": {
"newRoot": {
results: {
$filter: {
input: [
"aaa",
"bbb",
"ccc"
],
as: "datum",
cond: {
$not: {
"$setIsSubset": [
[
"$$datum"
],
"$names"
]
}
}
}
}
}
}
}
])
正如您所知道的,这两种方法都需要您将所有名称加载到内存中,没有办法解决这个问题,如果您的数据库规模对于这些方法来说太大,您将不得不遍历查询输入并通过一。
const queryArr = ['aaa', 'bbb', 'ccc'];
for (let queryName of queryArr) {
const found = await db.collection.findOne({name: queryName})
if (!found) {
//ding
}
}
假设您在name 字段上有一个索引,这应该非常有效。
【讨论】: