我因无法(无论是单独还是通过SO)无法弄清楚如何直接在#+OPTIONS: num:nil toc:nil html-postamble:nil ^:nil
#+HTML_HEAD: <style type="text/css">
#+HTML_HEAD: .styledtable { width: 400px;}
#+HTML_HEAD: .styledtable col:nth-of-type(1) { width: 25%; background: yellow; }
#+HTML_HEAD: .styledtable col:nth-of-type(2) { width: 50%; background: magenta; }
#+HTML_HEAD: .styledtable col:nth-of-type(3) { width: 25%; background: cyan; }
#+HTML_HEAD: </style>
#+ATTR_HTML: :class styledtable
| column1 | column2 | column3 |
|---------+-------------+---------------------|
| small | medium text | very very long text |
或自定义类中提取深层嵌套的数据而感到厌烦。我知道我应该确定使用过滤器和投影来找出嵌套在另一个数组中的BsonDocument
数组/列表。
以下是结构(简化):
Guid
我同时使用//Thread
{
Id: "B2",
Answers: [
{
Id: "A1",
Likes: [ "GUID1", "GUID2", "ETC" ] //<- this array, and only this.
}
]
}
和Thread.Id
作为过滤数据,但随后尝试使用:
Answer.Id
但是此查询始终返回null,这是我从POV做错了什么?
答案 0 :(得分:2)
我无法通过单个过滤和投影来获取点赞。但是,我可以通过使用聚合管道来实现它。
private async Task<BsonArray> GetLikes(string docId, string answerId)
{
var client = new MongoClient();
var idFilter = Builders<BsonDocument>.Filter.Eq("ID", docId);
var answerIdFilter = Builders<BsonDocument>.Filter.Eq("Answers.ID", answerId);
var projection = Builders<BsonDocument>.Projection.Exclude("_id").Include("Answers.Likes");
var likes = await client.GetDatabase("test").GetCollection<BsonDocument>("items")
.Aggregate(new AggregateOptions())
.Match(idFilter)
.Unwind("Answers")
.Match(answerIdFilter)
.Project(projection)
.FirstOrDefaultAsync();
return likes == null ? null
: (likes.GetElement("Answers").Value as BsonDocument).GetElement("Likes").Value as BsonArray;
}
由于某种原因,结果包含原始结构的文档,而不是仅包含具有Likes
属性的文档,因此我之后必须进行一些后期处理。
答案 1 :(得分:2)
使用常规查询无法在投影中投影数组中的各个字段。
您最多可以使用常规查询来投影匹配元素,然后映射喜欢的对象。
类似
var f = Builders<BsonDocument>.Filter;
var filter = f.And(f.Eq("Id", ids.ThreadId), f.Eq("Answers.Id", ids.AnswerId));
var projection = Builders<BsonDocument>.Projection.Include("Answers.$");
var answer = await dbClient.GetCollection<BsonDocument>(nameof(Thread))
.Find(filter)
.Project(projection)
.FirstOrDefaultAsync();
或者,您可以将过滤器与具有聚合功能的map结合使用,以通过id匹配答案元素,然后通过投影来匹配like字段。
类似
var f = Builders<BsonDocument>.Filter;
var match = f.And(f.Eq("Id", ids.ThreadId), f.Eq("Answers.Id", ids.AnswerId));
var project = new BsonDocument("newRoot",
new BsonDocument("$arrayElemAt", new BsonArray {
new BsonDocument("$map",
new BsonDocument
{
{ "input",
new BsonDocument("$filter", new BsonDocument
{
{ "input", "$Answers"},
{"cond", new BsonDocument("$eq", new BsonArray { "$$this.Id", ids.AnswerId})}
})
},
{ "in", new BsonDocument("Likes", "$$this.UserLikes") }
}),
0}));
var pipeline = collection.Aggregate()
.Match(match)
.AppendStage<BsonDocument, BsonDocument, BsonDocument>(new BsonDocument("$replaceRoot", project));
var list = pipeline.ToList();