查询单个数组元素是否存在于MongoDB文档的数组中

4

有没有办法找出MongoDB文档数组中是否存在单个元素。



例如: 如果我有一个文档

{
    "_id": "A",
    "userId": "B",
    "selectedUsers": ["C", "D"]
}

我有另外一个数组,内容为["E", "C"]。我想编写一条查询语句,当提供userId和上述数组时,该查询语句的结果应为[false, true],因为"E"不在selectedUsers数组中,而"C"在selectedUsers数组中。
我知道我可以先找到具有给定userId的文档,然后对它使用Array.find()来查找各个元素。但我想知道是否有一种方法可以在mongodb查询中完成这个操作。
此外,我正在使用nodeJS和mongoose。
只是为了明确起见,我需要使用mongodb查询来获得与下面js代码相同的功能。
// req is the http request
// Selected is the mongoose Model for above document
// usersToCheck = ["E", "C"] (this is the second array)
const result = Selected.findOne({ userId: req.userId});
const { selectedUsers } = result;
const response = usersToCheck.map(uid => {
    if(selectedUsers.some(id => id === uid)){
        return true;
    }
    return false;
})

// response = [false, true]

假设 usersToCheck 和 selectedUsers 的大小均为n,那么上述代码的复杂度为O(n^2)。

我想以某种方式使用mongodb查询来获得与上述相同的响应。这样,我就可以根据 selectedUsers 数组对集合进行索引,并提高获取响应所需的时间。

或者,您有任何其他改进上述代码的方法都可以。

非常感谢您的帮助。


确定一下:另一个数组 ["E", "C"] 存储在哪里?是在同一个文档中还是来自应用程序?查询需要检查 selectedUsers 是否没有 "E",但有 "C" 吗? - Valijon
@Valijon,第二个数组随着 HTTP 请求一起发送,查询需要返回一个数组,如果相应元素存在于文档的 selectedUsers 中,则相应位置为 true/false。 - war-turtle
3个回答

2
尝试这个:
const result = Selected.aggregate([
  {
    $match: {
      userId: req.userId
    }
  },
  {
    $project: {
      _id: 0,
      result: {
        $map: {
          input: ["E", "C"],
          in: {
            $in: [
              "$$this",
              "$selectedUsers"
            ]
          }
        }
      }
    }
  }
]).exec();
const response = result[0].result;

MongoPlayground


谢谢,这个很好用。但是它能改善时间复杂度吗?我的意思是,我应该使用这个查询来改变我的 js 代码吗? - war-turtle
@war-turtle 它具有相同的时间复杂度,但在服务器端执行(在MongoDB内部)。您所需要做的就是从结果中返回result属性。 - Valijon

1
你可以直接使用$in
db.collection.find({selectedUsers: {$in: ["E", "C"]}})

这将获取选择用户数组中存在 E 或 C 的文档,从我的理解来看,他只想检查一个特定文档中是否存在 E 或 C。 - Anuj Pancholi

1
这个怎么样?
var input = ['E', 'C'];

db.collection.aggregate(
    [
        {
            $match: {
                _id: 'A'
            }
        },
        {
            $unwind: '$selectedUsers'
        },
        {
            $set: {
                has: { $in: ['$selectedUsers', input] }
            }
        },
        {
            $group: {
                _id: null,
                result: { $push: '$has' }
            }
        },
        {
            $project: {
                _id: 0
            }
        }
    ])

查询结果按照selectedUsers的顺序返回。感谢您的回答,我认为这个查询给了我解决问题的正确思路。 - war-turtle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接