【发布时间】:2017-06-11 12:22:41
【问题描述】:
我的数据库中有两个集合:
// UnifiedPost
public class UnifiedPost
{
public UnifiedPost() { Id = ObjectId.GenerateNewId(); }
[BsonId]
public ObjectId Id { get; set; }
public int OriginalId { get; set; }
public string Thumbnail { get; set; }
public string Preview { get; set; }
[AlsoNotifyFor("IsVideo")]
public string FullSized { get; set; }
public char Rating { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string Dimensions { get { return string.Format("{0}x{1}", Width, Height); } }
public int Score { get; set; }
[MongoDB.Bson.Serialization.Attributes.BsonIgnore]
public string Tags { get; set; }
public ICollection<ObjectId> TagIds { get; set; }
public char Site { get; set; }
public bool IsVideo { get { return FullSized.Contains(".mp4") || FullSized.Contains(".webm"); } }
public string UniversalId { get; set; } // UNIQUE index (Site + Original id; fe. S3001)
}
// Tag
public class Tag
{
public Tag() { }
public ObjectId Id { get; set; }
public string Name { get; set; }
}
我正在尝试创建一个 WebAPI 端点以从数据库中查询帖子:
[HttpGet, Route("post")]
public UnifiedPost[] GetPosts(string tags = null, string sites = "RSGLY", string rating = null,int page = 0, int limit = 100, string sort = "id:desc")
{
if (limit == 0 || limit > 100) limit = 100;
var toSkip = page * limit;
var tagArray = tags.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var siteArray = sites.ToCharArray();
var client = new MongoClient();
var db = client.GetDatabase("Booru");
var postsColl = db.GetCollection<UnifiedPost>("Posts");
var tagsColl = db.GetCollection<BooruScraper.Models.Tag>("Tags");
var tagIds = tagsColl.Find(o => tagArray.Contains(o.Name)).ToList().ToDictionary(o => o.Name, o => o.Id);
var query = postsColl.Find<UnifiedPost>(o => siteArray.Contains(o.Site) && tagIds.Values.All(p => o.TagIds.Contains(p))).Project<UnifiedPost>(Builders<UnifiedPost>.Projection.Expression(p => new UnifiedPost()
{
FullSized = p.FullSized,
Height = p.Height,
Id = p.Id,
OriginalId = p.OriginalId,
Preview = p.Preview,
Rating = p.Rating,
Score = p.Score,
Site = p.Site,
TagIds = new ObjectId[0],
Tags = string.Join(" ", tagsColl.Find(q => p.TagIds.Contains(q.Id), new FindOptions()).Project<string>(Builders<BooruScraper.Models.Tag>.Projection.Expression(r => r.Name)).ToList(CancellationToken.None)),
Thumbnail = p.Thumbnail,
UniversalId = p.UniversalId,
Width = p.Width
})).Skip(toSkip).ToList();
return query.ToArray();
}
坦率地说,这段代码很丑陋,甚至没有达到最低目的。这简直太可悲了,但我想不出任何方法可以用 Find Fluent API 做到这一点。
一方面,我想按用户输入的标签过滤所有帖子,如果没有输入标签,则不应用过滤器。但我不知道如何实现这一点,更不用说如何将所有其他过滤器(站点、排序、页面...)应用于find 查询。
我在这里缺少什么?如果Find 在这种情况下我应该使用什么?
谢谢!
编辑:用最简单的术语来说,我该怎么做:
- 从整个帖子集合中筛选出与输入标签匹配的帖子;
- 从该结果进一步过滤到仅用户输入的站点;
- 进一步过滤收藏并删除所有与输入评级不匹配的帖子;
- 页面、限制等
【问题讨论】:
标签: c# asp.net .net mongodb mongodb-query