C# MongoDB - 如何仅 select 嵌套属性
C# MongoDB - How to select nested properties only
这就是我的 类 的样子:
public class TestA : MongoDocument
{
public string ProjectID { get; set; }
public TestB Content { get; set; }
}
public class TestB
{
public string Id { get; set; }
public List<TestC> CustInfo { get; set; }
}
public class TestC
{
public string Id { get; set; }
public CustomerComment CustomerComment { get; set; }
}
public class CustomerComment
{
public string Id { get; set; }
public string notes { get; set; }
}
我只想 return 基于 TestA.ProjectID
&& TestC.Id
的 CustomerComment
var projection = Builders<TestA>.Projection
.Include(x => x.Content.CustInfo);
var options = new FindOptions<TestA>
{
Projection = projection
};
var find = await Collection.FindAsync(p => p.ProjectID == "555" &&
p.Content.CustInfo.Any(l => l.Id == "123"), options).ConfigureAwait(false);
var result = await find.ToListAsync().ConfigureAwait(false);
这有效,但它会 return 一切。在这种情况下,我只想 return CustomerComments.
所以为了只检索 customerComments,我根据 mongo 的结果进行了另一个查询。下面的代码为我提供了正确的数据,但我宁愿通过数据库进行过滤。
var test = result.SelectMany(x => x.Content.CustInfo.Where(l => l.Id == "123").Select(y => y.CustomerComment)).ToList();
我认为Aggregation Query可以满足您查询数据库中的数据并返回所需输出的要求。
$match
- 过滤数据。
$unwind
- 将数组字段解构为多个文档。
$match
- 为 Content.CustInfo
. 过滤数据
$replaceWith
- 用新文档替换当前文档进行输出。
db.collection.aggregate([
{
$match: {
"ProjectID": "555",
"Content.CustInfo.Id": "123"
}
},
{
$unwind: "$Content.CustInfo"
},
{
$match: {
"Content.CustInfo.Id": {
$eq: "123"
}
}
},
{
"$replaceWith": "$Content.CustInfo.CustomerComment"
}
])
解决方案 1:使用 AggregateFluent
Pre-requisite: 创建平仓 类.
public class UnwindTestA
{
public ObjectId _id { get; set; }
public string ProjectID { get; set; }
public UnwindTestB Content { get; set; }
}
public class UnwindTestB
{
public string Id { get; set; }
public TestC CustInfo { get; set; }
}
var result = await Collection.Aggregate()
.Match(
p => p.ProjectID == "555"
&& p.Content.CustInfo.Any(l => l.Id == "123")
)
.Unwind<TestA, UnwindTestA>(x => x.Content.CustInfo)
.Match<UnwindTestA>(x => x.Content.CustInfo.Id == "123")
.ReplaceWith<CustomerComment>("$Content.CustInfo.CustomerComment")
.ToListAsync();
解决方案 2:使用 BsonDocument
有时,使用 AggregateFluent
编写查询非常复杂。您可以使用转换为 BsonDocument
.
的 MongoDB 查询
BsonDocument[] aggregate = new BsonDocument[]
{
new BsonDocument("$match",
new BsonDocument
{
{ "ProjectID", "555" },
{ "Content.CustInfo.Id", "123" }
}),
new BsonDocument("$unwind", "$Content.CustInfo"),
new BsonDocument("$match",
new BsonDocument("Content.CustInfo.Id",
new BsonDocument("$eq", "123"))),
new BsonDocument("$replaceWith", "$Content.CustInfo.CustomerComment")
};
var result = await Collection.Aggregate<CustomerComment>(aggregate)
.ToListAsync();
Output
这就是我的 类 的样子:
public class TestA : MongoDocument
{
public string ProjectID { get; set; }
public TestB Content { get; set; }
}
public class TestB
{
public string Id { get; set; }
public List<TestC> CustInfo { get; set; }
}
public class TestC
{
public string Id { get; set; }
public CustomerComment CustomerComment { get; set; }
}
public class CustomerComment
{
public string Id { get; set; }
public string notes { get; set; }
}
我只想 return 基于 TestA.ProjectID
&& TestC.Id
var projection = Builders<TestA>.Projection
.Include(x => x.Content.CustInfo);
var options = new FindOptions<TestA>
{
Projection = projection
};
var find = await Collection.FindAsync(p => p.ProjectID == "555" &&
p.Content.CustInfo.Any(l => l.Id == "123"), options).ConfigureAwait(false);
var result = await find.ToListAsync().ConfigureAwait(false);
这有效,但它会 return 一切。在这种情况下,我只想 return CustomerComments.
所以为了只检索 customerComments,我根据 mongo 的结果进行了另一个查询。下面的代码为我提供了正确的数据,但我宁愿通过数据库进行过滤。
var test = result.SelectMany(x => x.Content.CustInfo.Where(l => l.Id == "123").Select(y => y.CustomerComment)).ToList();
我认为Aggregation Query可以满足您查询数据库中的数据并返回所需输出的要求。
$match
- 过滤数据。$unwind
- 将数组字段解构为多个文档。$match
- 为Content.CustInfo
. 过滤数据
$replaceWith
- 用新文档替换当前文档进行输出。
db.collection.aggregate([
{
$match: {
"ProjectID": "555",
"Content.CustInfo.Id": "123"
}
},
{
$unwind: "$Content.CustInfo"
},
{
$match: {
"Content.CustInfo.Id": {
$eq: "123"
}
}
},
{
"$replaceWith": "$Content.CustInfo.CustomerComment"
}
])
解决方案 1:使用 AggregateFluent
Pre-requisite: 创建平仓 类.
public class UnwindTestA
{
public ObjectId _id { get; set; }
public string ProjectID { get; set; }
public UnwindTestB Content { get; set; }
}
public class UnwindTestB
{
public string Id { get; set; }
public TestC CustInfo { get; set; }
}
var result = await Collection.Aggregate()
.Match(
p => p.ProjectID == "555"
&& p.Content.CustInfo.Any(l => l.Id == "123")
)
.Unwind<TestA, UnwindTestA>(x => x.Content.CustInfo)
.Match<UnwindTestA>(x => x.Content.CustInfo.Id == "123")
.ReplaceWith<CustomerComment>("$Content.CustInfo.CustomerComment")
.ToListAsync();
解决方案 2:使用 BsonDocument
有时,使用 AggregateFluent
编写查询非常复杂。您可以使用转换为 BsonDocument
.
BsonDocument[] aggregate = new BsonDocument[]
{
new BsonDocument("$match",
new BsonDocument
{
{ "ProjectID", "555" },
{ "Content.CustInfo.Id", "123" }
}),
new BsonDocument("$unwind", "$Content.CustInfo"),
new BsonDocument("$match",
new BsonDocument("Content.CustInfo.Id",
new BsonDocument("$eq", "123"))),
new BsonDocument("$replaceWith", "$Content.CustInfo.CustomerComment")
};
var result = await Collection.Aggregate<CustomerComment>(aggregate)
.ToListAsync();
Output