Mongodb递归搜索数组对象

huangapple go评论162阅读模式
英文:

Mongodb recursive search for array of objects

问题

我有一个树形结构,看起来像这样:

{
    "_id" : ObjectId("59aebe21f002a8556ca78310"),
    "fid" : ObjectId("59aebe216b96002252a89d7b"),
    "pr" : [

    ],
    "ch" : [
        {
            "_id" : ObjectId("59aebe326b96002252a89d7d"),
            "trashed" : false
        },
        {
            "_id" : ObjectId("59aebe376b96002252a89d7f"),
            "trashed" : false
        }
    ]
}
{
    "_id" : ObjectId("59aebe33f002a8556ca78347"),
    "fid" : ObjectId("59aebe326b96002252a89d7d"),
    "pr" : [
        {
            "_id" : ObjectId("59aebe216b96002252a89d7b"),
            "trashed" : false
        }
    ],
    "ch" : [
        {
            "_id" : ObjectId("59aebe3b6b96002252a89d81"),
            "trashed" : false
        }
    ]
}

其中 fid 是文件夹的ID,ch 是文件夹的子文件夹,所以我想要进行递归搜索以获取文件夹和文件的树形结构。
在我的情况下,我使用了 $graphLookup 来进行递归搜索,但结果中我也得到了其他文件夹。

pipeline := []bson.M{
    {"$match": bson.M{"fid": id}},
    {"$graphLookup": bson.M{
        "from":             "tree",
        "startWith":        "$fid",
        "connectFromField": "fid",
        "connectToField":   "ch._id",
        "as":               "parents",
    }},
    {"$match": bson.M{"ch.trashed": false}},
}

Connection.Session.DB("cctv_storage").C("tree").Pipe(pipeline).All(&tData)

我的项目是基于 Golang 的。

英文:

I have a tree structure look like this

{ 
    "_id" : ObjectId("59aebe21f002a8556ca78310"), 
    "fid" : ObjectId("59aebe216b96002252a89d7b"), 
    "pr" : [

    ], 
    "ch" : [
        {
            "_id" : ObjectId("59aebe326b96002252a89d7d"), 
            "trashed" : false
        }, 
        {
            "_id" : ObjectId("59aebe376b96002252a89d7f"), 
            "trashed" : false
        }
    ]
}
{ 
    "_id" : ObjectId("59aebe33f002a8556ca78347"), 
    "fid" : ObjectId("59aebe326b96002252a89d7d"), 
    "pr" : [
        {
            "_id" : ObjectId("59aebe216b96002252a89d7b"), 
            "trashed" : false
        }
    ], 
    "ch" : [
        {
            "_id" : ObjectId("59aebe3b6b96002252a89d81"), 
            "trashed" : false
        }
    ]
}

the fid is a folder id and the ch is the children of folder , so I want to do a recursive search to get tree of the folders and files.
In my case I have a used $graphLookup to do a recursive search but as a result I am getting other folders too

pipeline := []bson.M{
        {"$match": bson.M{"fid": id}},
		{"$graphLookup": bson.M{
			"from":             "tree",
			"startWith":        "$fid",
			"connectFromField": "fid",
			"connectToField":   "ch._id",
			"as":               "parents",
		}},
		{"$match": bson.M{"ch.trashed": false}},
	}

	Connection.Session.DB("cctv_storage").C("tree").Pipe(pipeline).All(&tData)

My project based on Golang.

答案1

得分: 1

我认为你需要先使用$unwind,然后再使用$graphLookup,这样你就可以进行递归搜索,就像这样:

var tData struct {
    Id    bson.ObjectId     `bson:"_id"`
    Child [][]bson.ObjectId `bson:"child"`
}

pipeline := []bson.M{
    {"$unwind": bson.M{
        "path": "pr",
        "preserveNullAndEmptyArrays": true,
    }},
    {"$graphLookup": bson.M{
        "from":             "tree",
        "startWith":        "$fid",
        "connectFromField": "fid",
        "connectToField":   "pr._id",
        "as":               "child",
    }},
    {"$match": bson.M{"fid": id}},
    {"$group": bson.M{"_id": id, "child": bson.M{"$addToSet": "$child.fid"}}},
}
Connection.Session.DB("cctv_storage").C("tree").Pipe(pipeline).One(&tData)

因此,你将获得根文件夹的id以及子文件夹的id。

英文:

I think you need to use $unwind for first, than $graphLookup, so you need to do a recursive search look like this

var tData struct {
		Id    bson.ObjectId     `bson:"_id"`
		Child [][]bson.ObjectId `bson:"child"`
	}

pipeline := []bson.M{
		{"$unwind": bson.M{
			"path": "$pr",
			"preserveNullAndEmptyArrays": true,
		}},
		{"$graphLookup": bson.M{
			"from":             "tree",
			"startWith":        "$fid",
			"connectFromField": "fid",
			"connectToField":   "pr._id",
			"as":               "child",
		}},
		{"$match": bson.M{"fid": id}},
		{"$group": bson.M{"_id": id, "child": bson.M{"$addToSet": "$child.fid"}}},
	}
Connection.Session.DB("cctv_storage").C("tree").Pipe(pipeline).One(&tData)

So as a result you will get the id of the root folder and the ids of children

huangapple
  • 本文由 发表于 2017年9月6日 16:03:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/46069871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定