簡體   English   中英

ZCCADCDEDB567ABAE643E15DCF0974E503Z 按子條件查找文檔

[英]Mongoose find documents by child criteria

我正在努力尋找在孩子身上具有特定屬性的所有文檔。 例如,我想找到所有孩子活動的用戶。

這些是我的模型

const userSchema = new mongoose.Schema({
    child: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'child'
    }
});

const childSchema = new mongoose.Schema({
    active: {
        type: Boolean,
        default: true
    }
});

我嘗試使用填充和匹配( .populate({path:'child', match: {active: true}}) ),但如果不活動,我將所有具有子屬性的用戶都設為 null。 我只需要有活躍孩子的用戶。 我所有的研究都使用點語法,但出於某種原因,我得到了一個空數組。 見下文:

let usersWithActiveChild = await User.find({'child.active': true}));
console.log(usersWithActiveChild) // --> displays '[]' 

謝謝你的幫助!

當您使用 ref 來引用另一個模式時,ZCCADCDEDB567ABAE643E15DCF0974E503Z 將文檔存儲在 MongoDB 中的單獨 collections 中。

存儲在用戶文檔的child字段中的實際值是DBRef

如果您直接查看 MongoDB 中的數據,您會發現類似以下內容:

用戶集合

{
  _id: ObjectId("5a934e000102030405000000")
  child: DBRef("child",ObjectId("5a934e000102030405000001"),"DatabaseName")
}

兒童收藏:

{

  _id: ObjectId("5a934e000102030405000001"),
  active: true
}

當您填充用戶 object 時,Mongoose 獲取用戶文檔,然后獲取子文檔。 正如您所指出的,由於已經檢索到用戶文檔,因此populate調用中的match過濾了子項。

只有當孩子作為子文檔存儲在 MongoDB 中時,才能使用點分符號'child.active' ,例如

{
  _id: ObjectId("5a934e000102030405000000")
  child:{
    _id: ObjectId("5a934e000102030405000001"),
    active: true
  }
}

但是您的孩子被定義為參考,因此情況並非如此。

為了根據引用子項的內容過濾用戶文檔列表,您需要
- 像您所做的那樣填充匹配,然后過濾結果集,或者
- 聚合用戶集合, 查找子文檔,然后匹配子字段。

這可以通過使用聚合框架輕松完成。

首先我們用$lookup加入兩個 collections 。 查找結果是數組,但是我們與 User 和 Child 的關系是一對一的,所以我們使用$arrayElemAt: ["$child", 0]得到第一項。

最后,我們使用$match應用我們的過濾器"child.active": true,

操場

  let usersWithActiveChild = await User.aggregate([
    {
      $lookup: {
        from: "childs",    //must be PHYSICAL collection name
        localField: "child",
        foreignField: "_id",
        as: "child",
      },
    },
    {
      $addFields: {
        child: {
          $arrayElemAt: ["$child", 0],
        },
      },
    },
    {
      $match: {
        "child.active": true,
      },
    },
  ]);

示例文檔:

db={
  "users": [
    {
      "_id": ObjectId("5a834e000102030405000000"),
      "child": ObjectId("5a934e000102030405000000")
    },
    {
      "_id": ObjectId("5a834e000102030405000001"),
      "child": ObjectId("5a934e000102030405000001")
    },
    {
      "_id": ObjectId("5a834e000102030405000002"),
      "child": ObjectId("5a934e000102030405000002")
    },

  ],
  "childs": [
    {
      "_id": ObjectId("5a934e000102030405000000"),
      "active": true
    },
    {
      "_id": ObjectId("5a934e000102030405000001"),
      "active": false
    },
    {
      "_id": ObjectId("5a934e000102030405000002"),
      "active": true
    }
  ]
}

Output:

[
  {
    "_id": ObjectId("5a834e000102030405000000"),
    "child": {
      "_id": ObjectId("5a934e000102030405000000"),
      "active": true
    }
  },
  {
    "_id": ObjectId("5a834e000102030405000002"),
    "child": {
      "_id": ObjectId("5a934e000102030405000002"),
      "active": true
    }
  }
]

或者作為一個更好的方法是首先獲得 activ child,然后像這樣查找用戶:

db.childs.aggregate([
  {
    $match: {
      "active": true
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "_id",
      foreignField: "child",
      as: "user"
    }
  }
])

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM