using Dpz.Core.Entity.Base;
using Dpz.Core.Entity.Base.Indexes;

namespace Dpz.Core.Public.Entity;

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(MembleCommenter), typeof(GuestCommenter))]
public abstract class Commenter
{
    /// <summary>
    /// 昵称
    /// </summary>
    public required string NickName { get; set; }
}

/// <summary>
/// 登录会员评论
/// </summary>
public class MembleCommenter : Commenter
{
    /// <summary>
    /// 头像
    /// </summary>
    public required string Avatar { get; set; }

    /// <summary>
    /// 身份标识
    /// </summary>
    public required string Identity { get; set; }
}

/// <summary>
/// 匿名评论
/// </summary>
public class GuestCommenter : Commenter
{
    /// <summary>
    /// 邮箱
    /// </summary>
    public required string Email { get; set; }

    /// <summary>
    /// 网站
    /// </summary>
    public string? Site { get; set; }
}

public class Comment : BaseEntity, IIndexedEntity<Comment>
{
    /// <summary>
    /// 评论类型
    /// </summary>
    [BsonRepresentation(BsonType.String)]
    public CommentNode Node { get; set; }

    /// <summary>
    /// 关联
    /// </summary>
    public required string Relation { get; set; }

    /// <summary>
    /// 回复时间
    /// </summary>
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
    public DateTime PublishTime { get; set; }

    /// <summary>
    /// 评论人
    /// </summary>
    public required Commenter Commenter { get; set; }

    /// <summary>
    /// 回复内容
    /// </summary>
    public required string CommentText { get; set; }

    /// <summary>
    /// 回复ID
    /// </summary>
    public List<ObjectId> Replies { get; set; } = [];

    /// <summary>
    /// 是否删除
    /// </summary>
    public bool IsDelete { get; set; }

    /// <inheritdoc />
    public static IReadOnlyList<EntityIndexDefinition> GetIndexDefinitions() =>
        [
            new()
            {
                Fields =
                [
                    EntityIndexField.Descending<Comment>(x => x.Node),
                    EntityIndexField.Descending<Comment>(x => x.Relation),
                ],
            },
            new() { Fields = [EntityIndexField.Ascending<Comment>(x => x.Node)] },
            new() { Fields = [EntityIndexField.Ascending<Comment>(x => x.Relation)] },
        ];
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这是一个基于MongoDB的评论系统实体类设计,使用了C#和MongoDB.Driver的特性。让我详细解释一下这个代码的结构和功能:

核心类结构

1. Commenter 抽象基类

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(MembleCommenter), typeof(GuestCommenter))]
public abstract class Commenter
  • 这是评论者的抽象基类,定义了所有评论者的共同属性
  • BsonDiscriminator(RootClass = true) 表示这是MongoDB多态序列化的根类
  • BsonKnownTypes 指定了该抽象类的具体实现类型,用于反序列化时的类型识别
  • 包含一个必需的 NickName 属性(昵称)

2. MembleCommenter - 会员评论者

public class MembleCommenter : Commenter
  • 继承自 Commenter,代表已登录的会员用户
  • 包含额外属性:
    • Avatar:头像
    • Identity:身份标识

3. GuestCommenter - 匿名评论者

public class GuestCommenter : Commenter
  • 继承自 Commenter,代表匿名访客
  • 包含额外属性:
    • Email:邮箱(必需)
    • Site:个人网站(可选)

4. Comment - 评论实体

public class Comment : BaseEntity, IIndexedEntity<Comment>
  • 继承自 BaseEntity(基础实体类)
  • 实现了 IIndexedEntity<Comment> 接口,用于定义数据库索引

Comment类的主要属性

  • Node: 评论类型,使用枚举存储为字符串格式
  • Relation: 关联标识(如文章ID、商品ID等)
  • PublishTime: 发布时间,存储为本地时间格式
  • Commenter: 评论者信息(多态,可以是会员或匿名用户)
  • CommentText: 评论内容
  • Replies: 回复列表,存储回复评论的ObjectId
  • IsDelete: 软删除标记

数据库索引设计

public static IReadOnlyList<EntityIndexDefinition> GetIndexDefinitions()

定义了三个索引:

  1. 复合索引: Node (降序) + Relation (降序) - 用于快速查询特定类型和关联的评论
  2. 单字段索引: Node (升序) - 用于按评论类型查询
  3. 单字段索引: Relation (升序) - 用于按关联对象查询

设计亮点

  1. 多态设计: 使用抽象类和继承处理不同类型的评论者,MongoDB会自动处理类型识别
  2. 软删除: 使用 IsDelete 标记而不是物理删除数据
  3. 嵌套回复: 通过 Replies 列表支持评论的回复功能
  4. 索引优化: 预定义了常用查询场景的索引,提高查询性能
  5. 类型安全: 使用 required 关键字确保必需属性不为空

这个设计适用于博客、电商、论坛等需要评论功能的系统,支持会员和匿名用户评论,并且具有良好的扩展性和查询性能。

评论加载中...