我有一个C#模型,该模型具有嵌套列表数组,并且已作为文档实现到Mongo中。
我想将数据返回到嵌套数组的结构中,但是我想基于父级上的字段和数组内的字段选择数据。
我尝试了ElemMatch和Project的数十种组合,但是现在我完全迷失了,甚至不确定是否可以使用驱动程序来完成我要尝试的操作。
public class Models
{
public ObjectId _id { get; set; }
public string ModelType{ get; set; }
public List<ModelList> ModelList { get; set; } = new List<ModelList>();
}
public class ModelList
{
public string ModelHashKey { get; set; }
public string ModelName { get; set; }
public string ModelAttribute { get; set; }
}
上面显示的数据模型。
我想从ModelList中选择所有记录,其中: Models.ModelType =“ Player” AND ModelList.ModelAttribute =“ Male”
即使这是Models的元素,我也想将数据返回到对象列表ModelList中。
您将如何解决此问题,还是只从父级中选择数据然后在C#中循环?
非常感谢,
戴夫
答案 0 :(得分:1)
因此,让我们从绘图板开始,并通过mongo控制台获取一些数据:
db.models.insertMany([
{
_id : 1,
ModelType: "Player",
ModelList: [
{ ModelHashKey: "1", ModelName: "1", ModelAttribute: "Male" },
{ ModelHashKey: "2", ModelName: "2", ModelAttribute: "Male" },
{ ModelHashKey: "3", ModelName: "3", ModelAttribute: "Female" }
]
},
{
_id : 2,
ModelType: "NotPlayer",
ModelList: [
{ ModelHashKey: "4", ModelName: "4", ModelAttribute: "Male" },
{ ModelHashKey: "5", ModelName: "5", ModelAttribute: "Male" },
{ ModelHashKey: "6", ModelName: "6", ModelAttribute: "Female" }
]
}
]);
从这个问题开始,我假设您只想选择_id为1的文档,还要将ModelLiet的列表过滤为2个Male(1、2)。
因此,让我们首先整理一下文档,这可以通过简单的查找来完成:
db.models.find({"ModelType": "Player", "ModelList.ModelAttribute": "Male"}).pretty()
请注意,我们可以添加索引
{"ModelType" : 1, "ModelList.ModelAttribute": 1 }
来支持该查询。
但是,如果执行此查找,我们将取回整个文档:
{
"_id" : 1,
"ModelType" : "Player",
"ModelList" : [
{
"ModelHashKey" : "1",
"ModelName" : "1",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "2",
"ModelName" : "2",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "3",
"ModelName" : "3",
"ModelAttribute" : "Female"
}
]
}
因此,在这里我们想将其转换为聚合查询并使用过滤器投影数据。
db.models.aggregate([
{ $match: {"ModelType": "Player", "ModelList.ModelAttribute": "Male" } },
{ $addFields: { "ModelList" : {
$filter: {
input: "$ModelList",
as: "item",
cond: { $eq: [ "$$item.ModelAttribute", "Male" ] }
}
}
}
}
]);
如果执行上述操作,我们将获得预期的结果(请在此处尝试-https://mongoplayground.net/p/j6bP9TE6aTD):
{
"_id" : 1,
"ModelType" : "Player",
"ModelList" : [
{
"ModelHashKey" : "1",
"ModelName" : "1",
"ModelAttribute" : "Male"
},
{
"ModelHashKey" : "2",
"ModelName" : "2",
"ModelAttribute" : "Male"
}
]
}
因此,我们使用MongoDB驱动程序将其隐藏到C#中,它们的语法非常相似,只是语法有所不同:
public class Models
{
public int _id { get; set; }
public string ModelType { get; set; }
public List<ModelList> ModelList { get; set; } = new List<ModelList>();
}
public class ModelList
{
public string ModelHashKey { get; set; }
public string ModelName { get; set; }
public string ModelAttribute { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<Models>("models");
var models = collection.Aggregate()
.Match(Builders<Models>.Filter.Eq(x => x.ModelType, "Player") & Builders<Models>.Filter.ElemMatch(x => x.ModelList, Builders<ModelList>.Filter.Eq(x => x.ModelAttribute, "Male")))
.AppendStage<Models>(BsonDocument.Parse(@"{ $addFields: { ""ModelList"" : { $filter: { input: ""$ModelList"", as: ""item"", cond: { $eq: [""$$item.ModelAttribute"", ""Male""] } } } } }"))
.ToList();
foreach (var model in models)
{
foreach (var item in model.ModelList)
{
Console.WriteLine(item.ToJson());
}
}
}
}
请注意,我们正在使用AppendStage<>
作为C#驱动程序,目前还不支持该聚合阶段。
现在,如果我们运行此C#代码,我们将得到以下结果:
{ "ModelHashKey" : "1", "ModelName" : "1", "ModelAttribute" : "Male" }
{ "ModelHashKey" : "2", "ModelName" : "2", "ModelAttribute" : "Male" }
答案 1 :(得分:1)
如果您不介意将ModelList
项存储在自己的集合中,这是我使用MongoDB.Entities
的解决方案,它不使用任何魔术字符串。
using System;
using MongoDB.Entities;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System.Linq;
public class Models : Entity
{
public string ModelType { get; set; }
public Many<ModelList> ModlList { get; set; }
public Models() => this.InitOneToMany(() => ModlList);
}
public class ModelList : Entity
{
public string ModelHashKey { get; set; }
public string ModelName { get; set; }
public string ModelAttribute { get; set; }
public One<Models> Parent { get; set; }
}
class Program
{
static void Main(string[] args)
{
new DB("test");
var parent = new Models { ModelType = "Player" };
parent.Save();
var ml1 = new ModelList
{
ModelAttribute = "Male",
ModelName = "i am one",
ModelHashKey = "secret",
Parent = parent.ToReference()
};
ml1.Save();
var ml2 = new ModelList
{
ModelAttribute = "Female",
ModelName = "i am two",
ModelHashKey = "secret",
Parent = parent.ToReference()
};
ml2.Save();
parent.ModlList.Add(ml1);
parent.ModlList.Add(ml2);
var result = (from m in DB.Collection<Models>()
where m.ModelType == "Player"
join l in DB.Collection<ModelList>() on m.ID equals l.Parent.ID into lists
from ml in lists
select ml).Where(l => l.ModelAttribute == "Male");
var modellists = result.ToArray();
Console.Write(modellists.First().ModelName);
Console.ReadKey();
}
}
产生的mongodb聚合:
aggregate([{
"$match" :
{ "ModelType" : "Player" } },
{ "$lookup" : {"from" : "ModelLists",
"localField" : "_id",
"foreignField" : "Parent.ID", "as" : "lists" } },
{ "$unwind" : "$lists" },
{ "$project" : { "lists" : "$lists", "_id" : 0 } },
{ "$match" : { "lists.ModelAttribute" : "Male" } }])