簡體   English   中英

使用mongoose查詢只獲取一個子文檔

[英]Use mongoose query to get only a subdocument

我有一個類似的數據結構:

var GrandGrandChild = mongoose.Schema({
    attribute: String,
    id: Number
});

var GrandChild = mongoose.Schema({
    children: [GrandGrandChild],
    id: Number,
    irrelevantAttribute: String
});

var Child = mongoose.Schema({
    children: [GrandChild],
    id: Number,
    irrelevantAttribute2: String
});

var Parent = mongoose.Schema({
    children: [Child],
    id: Number,
    irrelevantAttribute3: String
});

var GrandParent = mongoose.Schema({
    children: [Parent],
    id: Number,
    irrelevantAttribute4: String
});

這些是包含子文檔的很多集合。 請注意,ID對於其兄弟姐妹是唯一的,但對於具有相同模式的所有元素而言並非唯一。

因此,一個祖父母可以擁有身份0的父母,而另一個祖父母也可以擁有身份0的父母,但是一個祖父母不能擁有2個身份為0的父母。

保存的唯一模式是GrandParent模式,而mongoose / mongodb是這個祖父母的所有數據的一個很好的單個大文檔。 (正是我要找的)

所以這是我的問題:我有一個GrandParent ID,Parent ID,Child ID,GrandChildID和GrandGrandChild ID,我想以某種方式獲得所有這些ID所指向的GrandGrandChild對象。

丑陋的方式是,但目前我唯一可以開始工作的方法是創建一個獲取GrandParent這個大文檔的查詢,並手動循環遍歷所有數組以找到正確的Parent,然后再循環找到正確的孩子,然后再循環找到合適的孫子,然后再循環,找到我需要的grandgrandchild。

我的問題是,如何在mongoose中編寫一個查詢,該查詢只返回grandgrandchild文檔,或者只包含子屬性的祖父文檔,並且在子類屬性中只包含引用的子對象所包含的父對象引用grandgrandchild對象的孫子對象,允許以下結果:

GRANDPARENT  PARENT      CHILD      GRANDCHILD   GRANDGRANDCHILD
grandparent.children[0].children[0].children[0].children[0].attribute;

我希望有人可以幫我解決這個問題,我得到的是:

GrandParentModel.findOne(
    {
        "id" : 0,
        "children.id" : 0,
        "children.children.id" : 0,
        "children.children.children.id" : 0,
        "children.children.children.children.id" : 0
    },
    {"children.children.children.children.$" : 1}, callback);

這個問題的問題在於,不合情理的兄弟姐妹沒有被修剪掉。

我希望有人可以幫助我。

Hylke Bron

自從我提出這個問題以來已經有一段時間了,但我認為我找到了一種相當優雅的方式來處理這些結構。

在這種情況下,我將展示它如何僅適用於GrandParent,Parent和Child。

我沒有在每個文檔(GrandParent.children,Parent.children)中存儲子文檔列表,而是創建了以下結構的唯一標識符:

Child.referenceId = {
    grandparent: "some key to the grandparent of the parent",
    parent: "some key to the parent",
    child: "key of this child"
};

Parent.referenceId = {
    grandparent: "some key to its grandparent",
    parent: "key of this parent"
}

GrandParent.referenceId = {
    grandparent: "key of this parent"
}

這將創建GrandParent> Parent> Child的層次結構。

模型將類似於以下內容:

var idStructure = {
    grandparent: { type: String, required: true },
    parent: { type: String, required: false },
    child: { type: String, required: false }
};

var GrandParent = mongoose.Schema({
    id: idStructure,
    irrelevantAttribute: String
});

var Parent = mongoose.Schema({
    id: idSructure,
    irrelevantAttribute: String
});

var Child = mongoose.Schema({
    id: idStructure,
    irrelevantAttribute: String
});

請注意,父不直接知道它的父節點,因為它們不存儲為子文檔。 然而,通過referenceId,父母和孩子之間仍然存在聯系。

在搜索GrandParent的整個familytree時,只需執行3個查詢,然后正確連接它們:

// First find all children which belong to the grandparent
Child.find({"id.grandparent" : "some key to the grandparent"})
.exec(function(err, children)
{
     if(err)
         return;

     Parent.find({"id.grandparent" : "some key to the grandparent"})
     .exec(function(err, parents)
     {
         if(err)
             return;

         // Loop through the parents and children to connect them before returning to a client
         for(var i = 0; i < parents.length; i++)
         {
             var parent = parents[i];
             parent.children = [];
             // loop through the children to check if they belong to the current parent
             for(var j = 0; j < children.length; j++)
             {
                 var child = children[j];
                 if(parent.id.parent == child.id.parent)
                     parent.children.push(child);
             }
         }

         // After filling the children into the parents, get the grandparents and do the same for the parents and grandparents as done for the children and parents.
        GrandParent.find({"id.grandparent" : "some key to the grandparent"})
       .exec(function(err, grandparents)
       {
           // TODO: the same as done above (two loops, one loops the grandparents, other loops the parents
           // Once this is finished, we have a filled grandparent
       });

     });
});

上面的代碼只會導致一個祖父母,父母充滿了孩子。

不再找到祖父母的原因是因為祖父母的id應該是唯一的,因為祖父母的referenceId只有祖父母屬性。

我希望我明確指出,因為通過這種方法,人們可以輕松地搜索一個特定的孩子,通過引用ID輕松獲取其父級,並通過引用ID輕松獲取其祖父母。

它可能有點復雜,但是一旦你為自己想出了這個方法,它就會直截了當。

Hylke

很難讓這種東西以干凈的方式運作。

我沒有找到關於這個主題的干凈解決方案,但也許我可以幫助你解決循環問題。 您可以使用以下命令來避免循環:var doc = parent.children.id(id); 查找子文檔

我希望這對你有幫助。 此致,塞巴斯蒂安。

這對我有用

      model.find({_id:args.id},{ commentList: { $elemMatch: { _id: todo.commentList[todo.commentList.length-1] } } },(err, todos) => {
         if (err) reject(err)
         else resolve(todos)
         console.log(todos);
      })

$ elemMatch(投影)

暫無
暫無

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

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