繁体   English   中英

ASP.NET Core 5.0 和 MongoDB - 数据 model 和大量数据的关键数据类型

[英]ASP.NET Core 5.0 and MongoDB - data model and key data type for large amount of data

我实际上并没有尝试这样做,我只是在学习,但我真的很想知道什么是最好的解决方案,也许这里有一些专家愿意提供帮助。

举个最基本的例子:帖子集合,每个帖子都可以包含评论集合。 让我们假设大量数据。

public class Post
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public Guid Id { get; set; }
        public string PostBody { get; set; }
    }
public class Comment
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public Guid Id { get; set; }
        public Guid PostId { get; set; }
        public string CommentBody { get; set; }
    }

这个 model 没有嵌入,所以从技术上讲它应该更快,因为如果你只想显示帖子,不需要获得评论。 但是如果你想获得帖子和评论,你需要搜索整个评论集合。

而关于关键数据类型int太小, long int也最终会用完。 Guid也是有限的,但应该可以工作更长时间。

这个问题有最优解吗?

这个 model 没有嵌入,所以技术上应该更快

这是不正确的。 嵌入比连接/查找更快。 但是嵌入也有缺点。

  • 深度嵌套/嵌入的项目更难查询和更新。
  • 如果查询不需要嵌入项目,则需要使用投影排除嵌入项目。
  • 整个文档不能超过 16mb。 所以不适合无界 arrays。

另一方面,如果您使用 go 引用路由并将数据保存在单独的 collections 中,则您需要进行比检索嵌入文档慢的查找/连接。

但是如果你想获得帖子和评论,你需要搜索整个评论集合。

您不必搜索整个集合,因为默认情况下,集合的Id字段上有一个唯一索引。 进行查找/连接时将使用此索引。 如果从另一端开始查找,您可以轻松地为外部字段创建索引。 下面的例子。


int 太小,long int 也最终会用完。 Guid 也是有限的

正确的。 这就是 mongodb 具有ObjectId的原因,它可以在 99% 的场景中产生奇迹。


所以...对于您假设的帖子和评论场景,您实际上可以将评论嵌入帖子实体中。 因为根据评论正文的大小,您可能能够在单个帖子实体中存储数百条评论,同时将帖子的总数据大小保持在 16mb 以下。

理想情况下,应根据应用程序的查询模式做出嵌入与引用的决定,同时牢记 16mb 的限制。


这是一个使用MongoDB.Entities库(我是它的作者)的示例控制台程序,它简化了官方驱动程序的大部分仪式。 我选择了下面的参考路线。

using MongoDB.Driver;
using MongoDB.Entities;
using System.Threading.Tasks;

namespace TestApplication
{
    public class Post : Entity
    {
        public string Title { get; set; }
        public string Body { get; set; }
        public Many<Comment> Comments { get; set; }

        public Post()
            => this.InitOneToMany(() => Comments);
    }

    public class Comment : Entity
    {
        public One<Post> Post { get; set; }
        public string Body { get; set; }
    }

    public class PostWithComments : Post
    {
        public Comment[] CommentList { get; set; }
    }

    public static class Program
    {
        private static async Task Main()
        {
            await DB.InitAsync("test");

            //create some posts
            var post1 = new Post { Title = "post one", Body = "hellow world 1" };
            var post2 = new Post { Title = "post two", Body = "hellow world 2" };
            await new[] { post1, post2 }.SaveAsync();

            //create some comments
            var pst1comment1 = new Comment { Body = "post 1 comment 1", Post = post1 };
            var pst1comment2 = new Comment { Body = "post 1 comment 2", Post = post1 };
            var pst2comment1 = new Comment { Body = "post 2 comment 1", Post = post2 };
            var pst2comment2 = new Comment { Body = "post 2 comment 2", Post = post2 };
            await new[] { pst1comment1, pst1comment2, pst2comment1, pst2comment2 }.SaveAsync();

            //add the comments to the posts
            await post1.Comments.AddAsync(new[] { pst1comment1, pst1comment2 });
            await post2.Comments.AddAsync(new[] { pst2comment1, pst2comment2 });

            //retrieve 1st post only
            var p1 = await DB.Find<Post>()
                             .OneAsync(post1.ID);

            //retrieve comments of 1st post
            var p1comments = await DB.Find<Comment>()
                                     .Match(c => c.Post.ID == post1.ID)
                                     .ExecuteAsync();

            //retrieve 2nd post with comments
            var p2 = await DB.Fluent<Post>()
                             .Match(p => p.ID == post2.ID)
                             .Lookup<Post, Comment, PostWithComments>(
                                DB.Collection<Comment>(), //foreign collection to join
                                p => p.ID,                //local field
                                c => c.Post.ID,           //foreign field
                                pwc => pwc.CommentList)   //the field to store looked up comments
                             .ToListAsync();
        }
    }
}

在外部字段上创建索引以加快查找速度

await DB.Index<Comment>()
        .Key(c => c.Post.ID, KeyType.Ascending)
        .CreateAsync();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM