Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API实现)--学习笔记

.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API实现)--学习笔记

原创
作者头像
郑子铭
修改于 2021-01-07 02:11:45
修改于 2021-01-07 02:11:45
35400
代码可运行
举报
运行总次数:0
代码可运行

2.5.7 MongoDB -- API实现

  • 问题查询单个实现
  • 问题查询列表实现
  • 问题跨集合查询实现
  • 问题创建实现
  • 问题更新实现
  • 问题回答实现
  • 问题评论实现
  • 问题投票实现
  • 回答实现

QuestionController

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace LighterApi.Controller
{
    [ApiController]
    [Route("api/[controller]")]
    public class QuestionController : ControllerBase
    {
        private readonly IMongoCollection<Question> _questionCollection;

        private readonly IMongoCollection<Vote> _voteCollection;

        private readonly IMongoCollection<Answer> _answerCollection;

        public QuestionController(IMongoClient mongoClient)
        {
            var database = mongoClient.GetDatabase("lighter");

            _questionCollection = database.GetCollection<Question>("questions");
            _voteCollection = database.GetCollection<Vote>("votes");
            _answerCollection = database.GetCollection<Answer>("answers");
        }
    }
}

问题查询单个实现

linq 查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpGet]
[Route("{id}")]
public async Task<ActionResult<Question>> GetAsync(string id, CancellationToken cancellationToken)
{
    var question = await _questionCollection.AsQueryable()
        .FirstOrDefaultAsync(q => q.Id == id, cancellationToken: cancellationToken);
    if (question == null)
        return NotFound();

    return Ok(question);
}

mongo 查询表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
await _questionCollection.Find(filter).FirstOrDefaultAsync(cancellationToken);

构造空查询条件的表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var filter = string.IsNullOrEmpty(id)
    ? Builders<Question>.Filter.Empty
    : Builders<Question>.Filter.Eq(q => q.Id, id);

多段拼接 filter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var filter2 = Builders<Question>.Filter.And(filter, Builders<Question>.Filter.Eq(q => q.TenantId , "001"));

问题查询列表实现

  • 数据 AnyIn查询
  • 排序 sort : StirngFieldDefinition
  • 分页 skip, limit
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpGet]
public async Task<ActionResult<List<Question>>> GetListAsync([FromQuery] List<string> tags,
    CancellationToken cancellationToken, [FromQuery] string sort = "createdAt", [FromQuery] int skip = 0,
    [FromQuery] int limit = 10)
{
    //// linq 查询
    //await _questionCollection.AsQueryable().Where(q => q.ViewCount > 10)
    //    .ToListAsync(cancellationToken: cancellationToken);

    var filter = Builders<Question>.Filter.Empty;

    if (tags != null && tags.Any())
    {
        filter = Builders<Question>.Filter.AnyIn(q => q.Tags, tags);
    }

    var sortDefinition = Builders<Question>.Sort.Descending(new StringFieldDefinition<Question>(sort));

    var result = await _questionCollection
        .Find(filter)
        .Sort(sortDefinition)
        .Skip(skip)
        .Limit(limit)
        .ToListAsync(cancellationToken: cancellationToken);

    return Ok(result);
}

问题跨集合查询实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpGet]
[Route("{id}/answers")]
public async Task<ActionResult> GetWithAnswerAsync(string id, CancellationToken cancellationToken)
{
    // linq 查询
    var query = from question in _questionCollection.AsQueryable()
                where question.Id == id
                join a in _answerCollection.AsQueryable() on question.Id equals a.QuestionId into answers
                select new { question, answers };

    var result = await query.FirstOrDefaultAsync(cancellationToken);

    if (result == null)
        return NotFound();

    return Ok(result);
}

问题创建实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpPost]
public async Task<ActionResult<Question>> CreateAsync([FromBody] Question question,
    CancellationToken cancellationToken)
{
    question.Id = Guid.NewGuid().ToString();
    await _questionCollection.InsertOneAsync(question, new InsertOneOptions {BypassDocumentValidation = false},
        cancellationToken);
    return StatusCode((int) HttpStatusCode.Created, question);
}

问题更新实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpPatch]
[Route("{id}")]
public async Task<ActionResult> UpdateAsync([FromRoute] string id, [FromBody] QuestionUpdateRequest request,
    CancellationToken cancellationToken)
{
    if (string.IsNullOrEmpty(request.Summary))
        throw new ArgumentNullException(nameof(request.Summary));

    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);

    var update = Builders<Question>.Update
        .Set(q => q.Title, request.Title)
        .Set(q => q.Content, request.Content)
        .Set(q => q.Tags, request.Tags)
        .Push(q => q.Comments, new Comment { Content = request.Summary, CreatedAt = DateTime.Now });

    await _questionCollection.UpdateOneAsync(filter, update, cancellationToken: cancellationToken);

    return Ok();
}

使用拼接的方式构建表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var updateFieldList = new List<UpdateDefinition<Question>>();

if (!string.IsNullOrWhiteSpace(request.Title))
    updateFieldList.Add(Builders<Question>.Update.Set(q => q.Title, request.Title));

if (!string.IsNullOrWhiteSpace(request.Content))
    updateFieldList.Add(Builders<Question>.Update.Set(q => q.Content, request.Content));

if (request.Tags != null && request.Tags.Any())
    updateFieldList.Add(Builders<Question>.Update.Set(q => q.Tags, request.Tags));

updateFieldList.Add(Builders<Question>.Update.Push(q => q.Comments,
    new Comment {Content = request.Summary, CreatedAt = DateTime.Now}));

var update = Builders<Question>.Update.Combine(updateFieldList);

问题回答实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpPost]
[Route("{id}/answer")]
public async Task<ActionResult<Answer>> AnswerAsync([FromRoute] string id, [FromBody] AnswerRequest request,
    CancellationToken cancellationToken)
{
    var answer = new Answer {QuestionId = id, Content = request.Content, Id = Guid.NewGuid().ToString()};
    _answerCollection.InsertOneAsync(answer, cancellationToken);

    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
    var update = Builders<Question>.Update.Push(q => q.Answers, answer.Id);

    await _questionCollection.UpdateOneAsync(filter, update, null, cancellationToken);

    return Ok();
}

问题评论实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpPost]
[Route("{id}/comment")]
public async Task<ActionResult> CommentAsync([FromRoute] string id, [FromBody] CommentRequest request,
    CancellationToken cancellationToken)
{
    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
    var update = Builders<Question>.Update.Push(q => q.Comments,
        new Comment {Content = request.Content, CreatedAt = DateTime.Now});

    await _questionCollection.UpdateOneAsync(filter, update, null, cancellationToken);

    return Ok();
}

问题投票实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[HttpPost]
[Route("{id}/up")]
public async Task<ActionResult> UpAsync([FromBody] string id, CancellationToken cancellationToken)
{
    var vote = new Vote
    {
        Id = Guid.NewGuid().ToString(),
        SourceType = ConstVoteSourceType.Question,
        SourceId = id,
        Direction = EnumVoteDirection.Up
    };

    await _voteCollection.InsertOneAsync(vote, cancellationToken);

    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
    var update = Builders<Question>.Update.Inc(q => q.VoteCount, 1).AddToSet(q => q.VoteUps, vote.Id);
    await _questionCollection.UpdateOneAsync(filter, update);

    return Ok();
}

[HttpPost]
[Route("{id}/down")]
public async Task<ActionResult> DownAsync([FromBody] string id, CancellationToken cancellationToken)
{
    var vote = new Vote
    {
        Id = Guid.NewGuid().ToString(),
        SourceType = ConstVoteSourceType.Question,
        SourceId = id,
        Direction = EnumVoteDirection.Down
    };

    await _voteCollection.InsertOneAsync(vote, cancellationToken);

    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
    var update = Builders<Question>.Update.Inc(q => q.VoteCount, -1).AddToSet(q => q.VoteDowns, vote.Id);
    await _questionCollection.UpdateOneAsync(filter, update);

    return Ok();
}

回答实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace LighterApi.Controller
{
    [ApiController]
    [Route("api/[controller]")]
    public class AnswerController : ControllerBase
    {
        private readonly IMongoCollection<Vote> _voteCollection;

        private readonly IMongoCollection<Answer> _answerCollection;

        public AnswerController(IMongoClient mongoClient)
        {
            var database = mongoClient.GetDatabase("lighter");

            _voteCollection = database.GetCollection<Vote>("votes");
            _answerCollection = database.GetCollection<Answer>("answers");
        }

        [HttpGet]
        public async Task<ActionResult<Answer>> GetListAsync([FromQuery] string questionId, CancellationToken cancellationToken)
        {
            var list = await _answerCollection.AsQueryable().Where(a => a.QuestionId == questionId)
                .ToListAsync(cancellationToken);
            return Ok(list);
        }

        [HttpPatch]
        [Route("{id}")]
        public async Task<ActionResult> UpdateAsync(string id, string content, string summary,
            CancellationToken cancellationToken)
        {
            var filter = Builders<Answer>.Filter.Eq(q => q.Id, id);

            var update = Builders<Answer>.Update
                .Set(q => q.Content, content)
                .Push(q => q.Comments, new Comment { Content = summary, CreatedAt = DateTime.Now });

            await _answerCollection.UpdateOneAsync(filter, update, cancellationToken: cancellationToken);

            return Ok();
        }

        [HttpPost]
        [Route("{id}/comment")]
        public async Task<ActionResult> CommentAsync([FromRoute] string id, [FromBody] CommentRequest request,
    CancellationToken cancellationToken)
        {
            var filter = Builders<Answer>.Filter.Eq(q => q.Id, id);
            var update = Builders<Answer>.Update.Push(q => q.Comments,
                new Comment { Content = request.Content, CreatedAt = DateTime.Now });

            await _answerCollection.UpdateOneAsync(filter, update, null, cancellationToken);

            return Ok();
        }

        [HttpPost]
        [Route("{id}/up")]
        public async Task<ActionResult> UpAsync([FromBody] string id, CancellationToken cancellationToken)
        {
            var vote = new Vote
            {
                Id = Guid.NewGuid().ToString(),
                SourceType = ConstVoteSourceType.Answer,
                SourceId = id,
                Direction = EnumVoteDirection.Up
            };

            await _voteCollection.InsertOneAsync(vote, cancellationToken);

            var filter = Builders<Answer>.Filter.Eq(q => q.Id, id);
            var update = Builders<Answer>.Update.Inc(q => q.VoteCount, 1).AddToSet(q => q.VoteUps, vote.Id);
            await _answerCollection.UpdateOneAsync(filter, update);

            return Ok();
        }

        [HttpPost]
        [Route("{id}/down")]
        public async Task<ActionResult> DownAsync([FromBody] string id, CancellationToken cancellationToken)
        {
            var vote = new Vote
            {
                Id = Guid.NewGuid().ToString(),
                SourceType = ConstVoteSourceType.Answer,
                SourceId = id,
                Direction = EnumVoteDirection.Down
            };

            await _voteCollection.InsertOneAsync(vote, cancellationToken);

            var filter = Builders<Answer>.Filter.Eq(q => q.Id, id);
            var update = Builders<Answer>.Update.Inc(q => q.VoteCount, -1).AddToSet(q => q.VoteDowns, vote.Id);
            await _answerCollection.UpdateOneAsync(filter, update);

            return Ok();
        }
    }
}

GitHub源码链接:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/LighterApi

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API重构)--学习笔记
将业务从controller 抽取到 Lighter.Application 层,并为业务建立抽象接口 Lighter.Application.Contract层
郑子铭
2021/01/07
5370
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API重构)--学习笔记
.NET 云原生架构师训练营(KestrelServer源码分析)--学习笔记
理解 KestrelServer 如何接收网络请求,网络请求如何转换成 http request context(C# 可识别)
郑子铭
2022/01/17
3250
.NET 云原生架构师训练营(KestrelServer源码分析)--学习笔记
.NET 云原生架构师训练营(组合模式)--学习笔记
在上一篇执行 _connectionDelegate 之后,HttpConnectionMiddleware 处理请求
郑子铭
2022/01/06
4060
.NET 云原生架构师训练营(组合模式)--学习笔记
.NET 云原生架构师训练营(权限系统 代码重构)--学习笔记
新增 AuthenticationController 用于登录和注册;登录会颁发 jwt token,包含用户的 claims 和 role 的 claims
郑子铭
2022/02/21
3640
.NET 云原生架构师训练营(权限系统 代码重构)--学习笔记
.NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记
创建 ResourceController,通过 ResourceManager 获取所有 Resource
郑子铭
2022/02/21
3320
.NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
乐观处理:系统认为数据的更新在大多数情况下是不会产生冲突的,只在数据库更新操作提交的时候才对数据作冲突检测(推荐)
郑子铭
2020/12/31
6460
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
.NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 详解)--学习笔记
消费者的类型包括:普通消费者,saga,saga 状态机,路由活动(分布式追踪),处理器 handlers,工作消费者 job comsumers
郑子铭
2021/01/28
6640
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
在范式化的情况下需要在进行多次查询再拼装数据,或者使用 lookup,即跨表查询;反范式化的情况下可以直接查出相关数据
郑子铭
2021/01/05
3760
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
.NET Core MongoDB数据仓储和工作单元模式实操
  上一章节我们主要讲解了MongoDB数据仓储和工作单元模式的封装,这一章节主要讲的是MongoDB用户管理相关操作实操。如:获取所有用户信息、获取用户分页数据、通过用户ID获取对应用户信息、添加用户信息、事务添加用户信息、用户信息修改、用户信息删除等实战教程。
追逐时光者
2023/04/17
8160
.NET Core MongoDB数据仓储和工作单元模式实操
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 介绍)--学习笔记
一个工作单元在一个事务范围内保留所有对数据库的变更,在这个工作单元结束的时候一次性提交所有改动到数据库
郑子铭
2020/12/27
1.1K0
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 介绍)--学习笔记
.NET MongoDB数据仓储和工作单元模式封装
在.NET开发中,MongoDB作为一种高性能、灵活的NoSQL数据库,常用于存储和管理大量数据。为了更好地组织代码结构,提高开发效率和代码可维护性,可以将数据访问层与业务逻辑层解耦,使用数据仓储(Repository)模式和工作单元(UnitOfWork)模式来封装MongoDB数据库操作。数据仓储模式通过抽象出通用的CRUD方法,使业务逻辑层无需关心数据的存储细节;工作单元模式则负责协调多个仓储操作,统一管理事务,确保数据的一致性。
郑子铭
2025/01/22
2090
.NET MongoDB数据仓储和工作单元模式封装
.NET 云原生架构师训练营(模块二 基础巩固 Host)--学习笔记
2.2.4 核心模块--Host 什么是 Host Host 的默认配置做了哪些事情 框架提供的服务 HostedService 后台服务 ASP.NET Core Web 主机:https://do
郑子铭
2021/01/13
3920
.NET 云原生架构师训练营(ASP .NET Core 整体概念推演)--学习笔记
ASP .NET Core 其实就是通过 web framework 处理 HTTP 请求并提供 HTTP 响应
郑子铭
2021/12/30
3400
.NET 云原生架构师训练营(ASP .NET Core 整体概念推演)--学习笔记
.NET 云原生架构师训练营(模块二 基础巩固 路由与终结点)--学习笔记
2.3.3 Web API -- 路由与终结点 路由模板 约定路由 特性路由 路由冲突 终结点 ASP.NET Core 中的路由:https://docs.microsoft.com/zh-cn/a
郑子铭
2020/12/22
4770
.NET 云原生架构师训练营(模块二 基础巩固 路由与终结点)--学习笔记
.NET Core MongoDB数据仓储和工作单元模式封装
上一章我们把系统所需要的MongoDB集合设计好了,这一章我们的主要任务是使用.NET Core应用程序连接MongoDB并且封装MongoDB数据仓储和工作单元模式,因为本章内容涵盖的有点多关于仓储和工作单元的使用就放到下一章节中讲解了。仓储模式(Repository )带来的好处是一套代码可以适用于多个类,把常用的CRUD通用方法抽象出来通过接口形式集中管理,从而解除业务逻辑层与数据访问层之间的耦合,使业务逻辑层在存储、访问数据库时无须关心数据的来源及存储方式。工作单元模式(UnitOfWork)它是用来维护一个由已经被业务修改(如增加、删除和更新等)的业务对象组成的列表,跨多个请求的业务,统一管理事务,统一提交从而保障事物一致性的作用。
追逐时光者
2023/04/28
1.6K0
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记
加载相关数据:https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/
郑子铭
2020/12/30
1.3K0
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记
ASP.NET 6 使用工作单元操作 MongoDB
最近工作中需要用到MongoDB的事务操作,因此参考了一些资料封装了一个小的组件,提供基础的CRUD Repository基类 和 UnitOfWork工作单元模式。今天,就来简单介绍一下这个小组件。
Edison Zhou
2023/07/21
4270
ASP.NET 6 使用工作单元操作 MongoDB
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 写入和查询)--学习笔记
https://docs.mongodb.com/manual/tutorial/insert-documents/
郑子铭
2021/01/02
7620
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 写入和查询)--学习笔记
.NET MongoDB Driver 2.2使用示例
说明:mongoDBService是对各种常用操作的封装 public class MongoDBService { #region 变量 /// <summary> /// 缓存 /// </summary> private static ConcurrentDictionary<string, Lazy<MongoClient>> m_mongoClientCache = new Concurren
甜橙很酸
2018/03/08
1.2K0
.NET MongoDB Driver 2.2使用示例
.NET 云原生架构师训练营(模块二 基础巩固 Host)--学习笔记
2.2.4 核心模块--Host 什么是 Host Host 的默认配置做了哪些事情 框架提供的服务 HostedService 后台服务 ASP.NET Core Web 主机:https://do
郑子铭
2020/12/17
6060
.NET 云原生架构师训练营(模块二 基础巩固 Host)--学习笔记
推荐阅读
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API重构)--学习笔记
5370
.NET 云原生架构师训练营(KestrelServer源码分析)--学习笔记
3250
.NET 云原生架构师训练营(组合模式)--学习笔记
4060
.NET 云原生架构师训练营(权限系统 代码重构)--学习笔记
3640
.NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记
3320
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
6460
.NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 详解)--学习笔记
6640
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
3760
.NET Core MongoDB数据仓储和工作单元模式实操
8160
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 介绍)--学习笔记
1.1K0
.NET MongoDB数据仓储和工作单元模式封装
2090
.NET 云原生架构师训练营(模块二 基础巩固 Host)--学习笔记
3920
.NET 云原生架构师训练营(ASP .NET Core 整体概念推演)--学习笔记
3400
.NET 云原生架构师训练营(模块二 基础巩固 路由与终结点)--学习笔记
4770
.NET Core MongoDB数据仓储和工作单元模式封装
1.6K0
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记
1.3K0
ASP.NET 6 使用工作单元操作 MongoDB
4270
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB 写入和查询)--学习笔记
7620
.NET MongoDB Driver 2.2使用示例
1.2K0
.NET 云原生架构师训练营(模块二 基础巩固 Host)--学习笔记
6060
相关推荐
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API重构)--学习笔记
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验