Mongodb C# - 仅当嵌套数组的嵌套元素符合条件时才进行聚合 $push
Mongodb C# - aggregation $push only if nested element of the nested array match the condition
我已经在网上看了很多,但我找不到解决办法...
有一个例子是我的类和对象:
类:
public class A {
[BsonId]
public int _id {get; set;}
public List<B> ListOfB {get; set;}
public TypeA Type {get; set;}
}
public class B {
public int _id {get; set;}
public int PersonId {get; set;}
public Person Person {get; set;} // This one is not save on the DB, it is retrieved through a Lookup
public int Type {get; set;}
}
public class Person {
[BsonId]
public int _id {get; set;}
public string Name {get; set;}
}
对象:
{
"_id": 0;
"Type", 0,
"ListOfB": [
{
"_id": 0,
"PersonId": 300,
"Type": 0
},
{
"_id": 1,
"PersonId": 24,
"Type": 0
},
{
"_id": 2,
"PersonId": 59,
"Type": 1
}
]
},
{
"_id": 1;
"Type", 1,
"ListOfB": [
{
"_id": 0,
"PersonId": 45,
"Type": 1
},
{
"_id": 1,
"PersonId": 102,
"Type": 0
},
{
"_id": 2,
"PersonId": 33,
"Type": 1
}
]
}
,
{
"_id": 2;
"Type", 1,
"ListOfB": [
{
"_id": 0,
"PersonId": 66,
"Type": 1
},
{
"_id": 1,
"PersonId": 89,
"Type": 0
},
{
"_id": 2,
"PersonId": 404,
"Type": 0
}
]
}
B是A集合的一部分,没有B集合。
到目前为止,我已经做了类似这样的事情来检索对象:
BsonDocument groupMappingA = new BsonDocument();
groupMappingA.Add(new BsonElement("_id", "$_id"));
BsonDocument groupMappingB = new BsonDocument();
groupMappingB.Add(new BsonElement("_id", "$ListOfB._id"));
groupMappingB.Add(new BsonElement("PersonId", "$ListOfB.PersonId"));
groupMappingB.Add(new BsonElement("Person", "$ListOfB.Person"));
groupMappingB.Add(new BsonElement("Type", "$ListOfB.Type"));
groupMappingA.Add(new BsonElement("ListOfB", new BsonDocument(
"$push", new BsonDocument(
"$cond", new BsonArray {
new BsonDocument("$eq", new BsonDocument("$ListOfB.Type", "0")),
new BsonDocument("$ListOfB", groupMappingB)
}
)
)
)
);
AggregateUnwindOptions<A> unwindOptions = new AggregateUnwindOptions<A>() { PreserveNullAndEmptyArrays = true };
db.GetCollection<A>("A").Aggregate()
.match(x => x.Type == 1)
.Unwind("ListOfB", unwindOptions)
.Lookup("Person", "ListOfB.PersonId", "_id", "ListOfB.Person") // Here we set up Person through the ID saved in the object B
.Unwind("ListOfB.Person", unwindOptions)
.Group(groupMappingA)
.As<A>()
.ToList();
所以我想要实现的是检索所有对象 A,并过滤所有对象 B 以仅获取类型等于 0 的对象,对于每个对象 B,我应该具有人物,例如:
{
"_id": 1;
"Type", 1,
"ListOfB": [
{
"_id": 1,
"PersonId": 102,
"Type": 0,
"Person": { "_id": 102, "Name": "Billy" }
}
]
},
{
"_id": 2;
"Type", 1,
"ListOfB": [
{
"_id": 1,
"PersonId": 89,
"Type": 0,
"Person": { "_id": 89, "Name": "Finn" }
},
{
"_id": 2,
"PersonId": 404,
"Type": 0,
"Person": { "_id": 404, "Name": "Jake" }
}
]
}
但这不起作用...我可以检索每个类型 1 的 A 对象,以及它们的 B 对象中的所有 Person 对象,但我得到了 B 的完整列表,而不仅仅是类型 0 的对象.
我先尝试在 Mongodb Compass 上做,但到目前为止,我没有成功,然后我在网上找了找,但找不到我要找的东西...我开始怀疑是否有可能在其嵌套列表中获取带有过滤器的对象?
预先感谢您的帮助。
我知道怎么做了,我把答案贴在这里以备不时之需。
BsonDocument groupMapping = new BsonDocument();
groupMapping.Add(new BsonElement("_id", new BsonDocument("$first", "$_id")));
groupMapping.Add(new BsonElement("ListOfB", new BsonDocument("$push", "$ListOfB")));
AggregateUnwindOptions<A> unwindOptions = new AggregateUnwindOptions<A>() { PreserveNullAndEmptyArrays = true };
db.GetCollection<A>("A").Aggregate()
.match(x => x.Type == 1)
.Unwind("ListOfB", unwindOptions)
.Match(new BsonDocument("ListOfB.Type", 0)) // Just put a match right after the Unwind, you'll be able to filter the elements of the list as you want.
.Lookup("Person", "ListOfB.PersonId", "_id", "ListOfB.Person")
.Unwind("ListOfB.Person", unwindOptions)
.Group(groupMapping)
.As<A>()
.ToList();
我已经在网上看了很多,但我找不到解决办法...
有一个例子是我的类和对象:
类:
public class A {
[BsonId]
public int _id {get; set;}
public List<B> ListOfB {get; set;}
public TypeA Type {get; set;}
}
public class B {
public int _id {get; set;}
public int PersonId {get; set;}
public Person Person {get; set;} // This one is not save on the DB, it is retrieved through a Lookup
public int Type {get; set;}
}
public class Person {
[BsonId]
public int _id {get; set;}
public string Name {get; set;}
}
对象:
{
"_id": 0;
"Type", 0,
"ListOfB": [
{
"_id": 0,
"PersonId": 300,
"Type": 0
},
{
"_id": 1,
"PersonId": 24,
"Type": 0
},
{
"_id": 2,
"PersonId": 59,
"Type": 1
}
]
},
{
"_id": 1;
"Type", 1,
"ListOfB": [
{
"_id": 0,
"PersonId": 45,
"Type": 1
},
{
"_id": 1,
"PersonId": 102,
"Type": 0
},
{
"_id": 2,
"PersonId": 33,
"Type": 1
}
]
}
,
{
"_id": 2;
"Type", 1,
"ListOfB": [
{
"_id": 0,
"PersonId": 66,
"Type": 1
},
{
"_id": 1,
"PersonId": 89,
"Type": 0
},
{
"_id": 2,
"PersonId": 404,
"Type": 0
}
]
}
B是A集合的一部分,没有B集合。 到目前为止,我已经做了类似这样的事情来检索对象:
BsonDocument groupMappingA = new BsonDocument();
groupMappingA.Add(new BsonElement("_id", "$_id"));
BsonDocument groupMappingB = new BsonDocument();
groupMappingB.Add(new BsonElement("_id", "$ListOfB._id"));
groupMappingB.Add(new BsonElement("PersonId", "$ListOfB.PersonId"));
groupMappingB.Add(new BsonElement("Person", "$ListOfB.Person"));
groupMappingB.Add(new BsonElement("Type", "$ListOfB.Type"));
groupMappingA.Add(new BsonElement("ListOfB", new BsonDocument(
"$push", new BsonDocument(
"$cond", new BsonArray {
new BsonDocument("$eq", new BsonDocument("$ListOfB.Type", "0")),
new BsonDocument("$ListOfB", groupMappingB)
}
)
)
)
);
AggregateUnwindOptions<A> unwindOptions = new AggregateUnwindOptions<A>() { PreserveNullAndEmptyArrays = true };
db.GetCollection<A>("A").Aggregate()
.match(x => x.Type == 1)
.Unwind("ListOfB", unwindOptions)
.Lookup("Person", "ListOfB.PersonId", "_id", "ListOfB.Person") // Here we set up Person through the ID saved in the object B
.Unwind("ListOfB.Person", unwindOptions)
.Group(groupMappingA)
.As<A>()
.ToList();
所以我想要实现的是检索所有对象 A,并过滤所有对象 B 以仅获取类型等于 0 的对象,对于每个对象 B,我应该具有人物,例如:
{
"_id": 1;
"Type", 1,
"ListOfB": [
{
"_id": 1,
"PersonId": 102,
"Type": 0,
"Person": { "_id": 102, "Name": "Billy" }
}
]
},
{
"_id": 2;
"Type", 1,
"ListOfB": [
{
"_id": 1,
"PersonId": 89,
"Type": 0,
"Person": { "_id": 89, "Name": "Finn" }
},
{
"_id": 2,
"PersonId": 404,
"Type": 0,
"Person": { "_id": 404, "Name": "Jake" }
}
]
}
但这不起作用...我可以检索每个类型 1 的 A 对象,以及它们的 B 对象中的所有 Person 对象,但我得到了 B 的完整列表,而不仅仅是类型 0 的对象.
我先尝试在 Mongodb Compass 上做,但到目前为止,我没有成功,然后我在网上找了找,但找不到我要找的东西...我开始怀疑是否有可能在其嵌套列表中获取带有过滤器的对象?
预先感谢您的帮助。
我知道怎么做了,我把答案贴在这里以备不时之需。
BsonDocument groupMapping = new BsonDocument();
groupMapping.Add(new BsonElement("_id", new BsonDocument("$first", "$_id")));
groupMapping.Add(new BsonElement("ListOfB", new BsonDocument("$push", "$ListOfB")));
AggregateUnwindOptions<A> unwindOptions = new AggregateUnwindOptions<A>() { PreserveNullAndEmptyArrays = true };
db.GetCollection<A>("A").Aggregate()
.match(x => x.Type == 1)
.Unwind("ListOfB", unwindOptions)
.Match(new BsonDocument("ListOfB.Type", 0)) // Just put a match right after the Unwind, you'll be able to filter the elements of the list as you want.
.Lookup("Person", "ListOfB.PersonId", "_id", "ListOfB.Person")
.Unwind("ListOfB.Person", unwindOptions)
.Group(groupMapping)
.As<A>()
.ToList();