C# .NET MongoDb-如何在n嵌套结构中插入要列出的元素
我有以下结构——为了简单起见,我缩写为。几乎没有财产。 如您所见,根文档(ProjectSchema)具有属性C# .NET MongoDb-如何在n嵌套结构中插入要列出的元素,c#,mongodb,linq,mongodb-query,C#,Mongodb,Linq,Mongodb Query,我有以下结构——为了简单起见,我缩写为。几乎没有财产。 如您所见,根文档(ProjectSchema)具有属性rootFolder(FolderSchema),该属性可以具有嵌套级别n。对于反序列化,我使用上面提到的用C#–ProjectSchema和FolderSchema编写的类 目标 将BsonDocument反序列化到我的自定义类ProjectSchema中,我需要按Id查找特定的文件夹,并在该文件夹中插入新的FolderSchema 问题 您能告诉我如何迭代,分别查找嵌套在n个级别的
rootFolder
(FolderSchema),该属性可以具有嵌套级别n。对于反序列化,我使用上面提到的用C#–ProjectSchema
和FolderSchema
编写的类目标 将BsonDocument反序列化到我的自定义类
ProjectSchema
中,我需要按Id查找特定的文件夹,并在该文件夹中插入新的FolderSchema
问题
您能告诉我如何迭代,分别查找嵌套在n个级别的特定文档,以及如何在找到的文档中插入元素吗
结构
{
"_id" : ObjectId("5abce10cb02728006f1460fd"),
"owner_ref" : ObjectId("5ababb7188f6ba0079199dd0"),
"description" : "",
"rootFolder" : [
{
"_id" : ObjectId("5abce10cb02728006f1460fc"),
"folders" : [
{
"_id" : ObjectId("5abce9b5b02728006f1460ff"),
"folders" : [
{
"_id" : ObjectId("5abd5775b02728006f146130"),
"folders" : [
{
"_id" : ObjectId("5abd5781b02728006f146131"),
"folders" : [
{
"_id" : ObjectId("5abd578ab02728006f146132"),
"folders" : [],
"fileRefs" : [],
"docs" : [],
"name" : "NSubFolder1"
}
],
"fileRefs" : [],
"docs" : [],
"name" : "SubSubFolder1"
}
],
"fileRefs" : [],
"docs" : [],
"name" : "SubFolder1"
}
],
"fileRefs" : [],
"docs" : [],
"name" : "Folder1"
},
{
"_id" : ObjectId("5abd576db02728006f14612f"),
"folders" : [],
"fileRefs" : [],
"docs" : [],
"name" : "Folder2"
}
],
"fileRefs" : [],
"docs" : [
{
"_id" : ObjectId("5abce10cb02728006f1460fe"),
"name" : "main.tex"
}
],
"name" : "rootFolder"
}
]
}
项目架构-它保存文件夹和其他属性。这是我的主要文件。
编辑: 用最简单的更新文档替换整个文档是一个好主意,我可以承认,它是有效的。但是,我的文档可能很大,所以我宁愿更新一个片段,而不是整个文档。但是,如果我选择部分更新,我仍然无法更新文档的某些部分,我不知道如何将其组合在一起。因此,我尝试了以下方法: 为了澄清,我知道
ProjectId
ProjectSchema-分别针对我想要更新文件夹的项目,以及我想要添加新文件夹的父文件夹FolderId
FolderSchema
//**Schema simplification:**
Project Schema
Folder Schema
Folder Schema
Folder Schema
[n level folder schema]
Folder Schema
[n level]
编写过滤器,以接收名为“NSubFolder1”的父文件夹,或者我将使用文件夹id而不是文件夹名称,因为我知道它
var eq = Builders<FolderSchema>.Filter.Eq(f => f.Name, "NSubFolder1");
var emN = Builders<FolderSchema>.Filter.ElemMatch(_ => _.Folders, eq);
var eq=Builders.Filter.eq(f=>f.Name,“NSubFolder1”);
var emN=Builders.Filter.ElemMatch(=>u0.Folders,eq);
用于接收要添加文件夹的项目的书面筛选器
var eqProj = Builders<ProjectSchema>.Filter.Eq(p => p.ProjectId, "project id here");
var emP = Builders<ProjectSchema>.Filter.ElemMatch(_ => _.ProjectId, eqProj);
var eqProj=Builders.Filter.Eq(p=>p.ProjectId,“此处为项目id”);
var emP=Builders.Filter.ElemMatch(=>.ProjectId,eqProj);
这两个过滤器如何组合在一起,以便在ProjectSchema下接收指定的FolderSchema,然后将新的FolderSchema推送到父数组?从概念上讲,您试图做的是构造一个任意深度的递归
$elemMatch
查询。我认为在当前的数据库设计中,用一个find/update命令是无法做到这一点的
似乎您事先知道顶级ProjectSchema
的ProjectId
——如果是这种情况,则可以检索该文档,遍历它,并构造一个n级深度FilterDefinition
,其描述如下(尽管编写方式不同)
var eq=Builders.Filter.eq(f=>f.Name,“HEUREKA”);
var emN=Builders.Filter.ElemMatch(=>u0.Folders,eq);
...
var em2=Builders.Filter.ElemMatch(\u=>\ u0.RootFolder,em3);
var em1=Builders.Filter.ElemMatch(\u=>\ u0.RootFolder,em2);
var-emRoot=Builders.Filter.ElemMatch(=>quot.RootFolder,em1);
尽管现在看来,在反序列化对象中添加新的FolderSchema
并替换数据库中的文档似乎是最简单的。尽管如此,如果不想替换整个文档,您可以用与生成ElemMatch查询大致相同的方式构造更新查询
如果您能够更改模式,以便在集合中插入多个
FolderSchema
对象,而不是一个任意深度的ProjectSchema
文档,那么您似乎可以使用MongoDb聚合框架$graphLookup
,如中所述,并在中提供更多示例
如果不了解你的情况,很难说这是一个更好的选择,或者仅仅是一个替代方案。使用MongoDB聚合框架的能力肯定是一个优势。不幸的是,我不能严格地更新模式——不管怎样,感谢graphLookup提示,将来肯定会使用它。您关于替换整个文档的提示非常有效。但是,我想知道一个解决方案,如何只更新文档的一部分。您知道,文档可能非常大,所以不要浪费资源。你介意看看我的问题吗?我仍在与之斗争。
//**Schema simplification:**
Project Schema
Folder Schema
Folder Schema
Folder Schema
[n level folder schema]
Folder Schema
[n level]
var eq = Builders<FolderSchema>.Filter.Eq(f => f.Name, "NSubFolder1");
var emN = Builders<FolderSchema>.Filter.ElemMatch(_ => _.Folders, eq);
var eqProj = Builders<ProjectSchema>.Filter.Eq(p => p.ProjectId, "project id here");
var emP = Builders<ProjectSchema>.Filter.ElemMatch(_ => _.ProjectId, eqProj);
var eq = Builders<FolderSchema>.Filter.Eq(f => f.Name, "HEUREKA");
var emN = Builders<FolderSchema>.Filter.ElemMatch(_ => _.Folders, eq);
...
var em2 = Builders<FolderSchema>.Filter.ElemMatch(_ => _.RootFolder, em3);
var em1 = Builders<FolderSchema>.Filter.ElemMatch(_ => _.RootFolder, em2);
var emRoot = Builders<ProjectSchema>.Filter.ElemMatch(_ => _.RootFolder, em1);