我有一个父元素列表,需要根据子列表中的结构进行过滤。
这是数据结构
"items": [
{
"id": "6691e62b-90as-43b2-k1l3-2fbf039295b5",
"details": {
"zone": {
"id": "cc07de83-3m21-1pp1-a123-a98bd8fb5fb8",
"name": "TestName",
}
},
}
]
var findresult = collection(f => f.items.Any(fb => fb.details.zone.name == "TestName")).ToList();
期望仅返回具有匹配区域名称的项目,但我只返回数据库中的所有内容
答案 0 :(得分:0)
要获取包含匹配子文档的父文档,您需要使用$elemMatch
运算符:
db.Parent.aggregate([
{
"$match": {
"items": {
"$elemMatch": {
"details.zone.name": "second zone"
}
}
}
}
])
如果只想获取匹配的子文档(项目),则需要$unwind
和$project
,如下所示:
db.Parent.aggregate([
{
"$unwind": "$items"
},
{
"$project": {
"items": "$items",
"_id": NumberInt("0")
}
},
{
"$match": {
"items.details.zone.name": "second zone"
}
}
])
这是上面查询生成的c#代码。代码使用MongoDB.Entities为简洁起见。查询部分与官方驱动程序相同。只需使用collection.AsQueryable()
代替DB.Queryable<Parent>()
using MongoDB.Driver.Linq;
using MongoDB.Entities;
using System;
using System.Linq;
namespace StackOverflow
{
public class Program
{
public class Parent : Entity
{
public Item[] items { get; set; }
}
public class Item
{
public string id { get; set; }
public Detail details { get; set; }
}
public class Detail
{
public string id { get; set; }
public Zone zone { get; set; }
}
public class Zone
{
public string id { get; set; }
public string name { get; set; }
}
private static void Main(string[] args)
{
new DB("test");
(new[] {
new Parent {
items = new[]
{
new Item
{
id = Guid.NewGuid().ToString(),
details = new Detail
{
id = Guid.NewGuid().ToString(),
zone = new Zone
{
id = Guid.NewGuid().ToString(),
name = "first zone"
}
}
}
}
},
new Parent {
items = new[]
{
new Item
{
id = Guid.NewGuid().ToString(),
details = new Detail
{
id = Guid.NewGuid().ToString(),
zone = new Zone
{
id = Guid.NewGuid().ToString(),
name = "second zone"
}
}
}
}
}
}).Save();
//get all Parent entities that have 'second zone'
var result = DB.Queryable<Parent>()
.Where(p => p.items.Any(i => i.details.zone.name == "second zone"))
.ToArray();
//get only items that have 'second zone'
var items = DB.Queryable<Parent>()
.SelectMany(p => p.items)
.Where(i => i.details.zone.name == "second zone")
.ToArray();
}
}
}
评论后更新:
为了获得父项并过滤出不匹配的子项,您需要一个$elemMatch
的投影台,如下所示:
db.Parent.find({
"items": {
"$elemMatch": {
"details.zone.name": "second zone"
}
}
}, {
"_id": NumberInt("1"),
"items": {
"$elemMatch": {
"details.zone.name": "second zone"
}
}
})
c#MongoDB。实体:
var result = DB.Find<Parent>()
.Match(p => p.items.Any(i => i.details.zone.name == "second zone"))
.Project(b =>
b.Include(p => p.ID)
.ElemMatch(p => p.items, i => i.details.zone.name == "second zone"))
.Execute();
c#官方驱动程序:
var projection = Builders<Parent>.Projection
.Include(p => p.ID)
.ElemMatch(p => p.items, i => i.details.zone.name == "second zone");
var result = collection.Find(p => p.items.Any(i => i.details.zone.name == "second zone"))
.Project(projection)
.ToList();