我有以下结构-为了简单起见,我缩写了一些属性。如您所见,根文档 (ProjectSchema) 具有属性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"
}
]
}
- Project schema**-这包含文件夹和其他属性。这是我的主文档。
public class ProjectSchema
{
[BsonId]
public BsonObjectId ProjectId { get; set; }
[BsonElement("description")]
public string Description { get; set; } = "some desc";
[BsonElement("owner_ref")]
public BsonObjectId OwnerRef { get; set; }
[BsonElement("rootFolder")]
public List<FolderSchema> RootFolder { get; set; } = new List<FolderSchema>();
public ProjectSchema()
{
ProjectId = new BsonObjectId(ObjectId.GenerateNewId());
}
}
- 文件夹架构**此架构包含文件夹
public class FolderSchema
{
[BsonId]
public BsonObjectId FolderId { get; set; }
[BsonElement("name")]
public string Name { get; set; } = "new folder";
[BsonElement("docs")]
public IEnumerable<DocSchema> Docs { get; set; } = new List<DocSchema>();
[BsonElement("fileRefs")]
public IEnumerable<FileSchema> FileRefs { get; set; } = new List<FileSchema>();
[BsonElement("folders")]
public IEnumerable<FolderSchema> Folders { get; set; } = new List<FolderSchema>();
public FolderSchema()
{
FolderId = new BsonObjectId(ObjectId.GenerateNewId());
}
}
我的尝试
不幸的是,这个工作没有成功,一切工作没有错误,但什么也没有发生。我假设有一个过滤器的错误,因为Any()
只针对第一级。我不知道如何针对FolderSchema嵌套n级。
- 初始调用**-在此示例中,我尝试在文件夹SubFolder1中添加名为 * HEUREKA * 的新文件夹
var projects = database.GetCollection<ProjectSchema>("projects");
var folder = new FolderSchema() { Name = "HEUREKA" };
var filter = Builders<ProjectSchema>.Filter.Where(p => p.ProjectId == new BsonObjectId(new ObjectId("5abce10cb02728006f1460fd"))
&& p.RootFolder.Any(l => l.FolderId == new BsonObjectId(new ObjectId("5abd5775b02728006f146130"))));
var update = Builders<ProjectSchema>.Update.Push(p => p.RootFolder, folder);
await projects.FindOneAndUpdateAsync(filter, update);
编辑次数:
这是一个很好的观点,用更新的文档替换整个文档,最简单的一个-我可以承认,**它工作。**然而,我的文档可以相当大,所以我宁愿更新一部分,而不是整个文档。然而,如果我选择部分更新的选项,我仍然无法更新我的文档的某些部分,我不知道如何把它放在一起。所以我试了下面的一个:
为了澄清,我知道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 eqProj = Builders<ProjectSchema>.Filter.Eq(p => p.ProjectId, "project id here");
var emP = Builders<ProjectSchema>.Filter.ElemMatch(_ => _.ProjectId, eqProj);
- 这两个筛选器如何组合在一起,以便接收ProjectSchema下指定的FolderSchema,然后将新的FolderSchema推送到父数组?**
1条答案
按热度按时间o7jaxewo1#
从概念上讲,您要做的是构造一个任意深度的递归
$elemMatch
查询,我认为在当前的数据库设计中,使用一个find/update命令是无法做到的。看起来好像您事先知道顶层
ProjectSchema
的ProjectId
-如果是这样的话,就可以检索该文档,遍历它,并构造一个n层深的FilterDefinition
,其描述如下(尽管写法不同)尽管此时,在反序列化对象中添加新的
FolderSchema
并替换数据库中的文档似乎是最简单的方法,但如果不想替换整个文档,您仍然可以用与生成ElemMatch查询相同的方法来构造Update查询。如果您能够更改模式,将多个
FolderSchema
对象插入到集合中,而不是插入一个任意深度的ProjectSchema
文档,那么您似乎可以使用MongoDb聚合框架$graphLookup
,如https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/中所述,更多示例请参见https://docs.mongodb.com/manual/tutorial/model-tree-structures/在不了解您的情况的情况下,很难说这是一个更好的选择,还是仅仅是一个替代方案,使用MongoDB Aggregate框架的能力应该被认为是一个加分项。