zoukankan      html  css  js  c++  java
  • .NET 云原生架构师训练营(模块二 基础巩固 MongoDB API实现)--学习笔记

    2.5.7 MongoDB -- API实现

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

    QuestionController

    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 查询

    [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 查询表达式

    var filter = Builders<Question>.Filter.Eq(q => q.Id, id);
    await _questionCollection.Find(filter).FirstOrDefaultAsync(cancellationToken);
    

    构造空查询条件的表达式

    var filter = string.IsNullOrEmpty(id)
        ? Builders<Question>.Filter.Empty
        : Builders<Question>.Filter.Eq(q => q.Id, id);
    

    多段拼接 filter

    var filter2 = Builders<Question>.Filter.And(filter, Builders<Question>.Filter.Eq(q => q.TenantId , "001"));
    

    问题查询列表实现

    • 数据 AnyIn查询
    • 排序 sort : StirngFieldDefinition
    • 分页 skip, limit
    [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);
    }
    

    问题跨集合查询实现

    [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);
    }
    

    问题创建实现

    [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);
    }
    

    问题更新实现

    [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();
    }
    

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

    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);
    

    问题回答实现

    [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();
    }
    

    问题评论实现

    [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();
    }
    

    问题投票实现

    [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();
    }
    

    回答实现

    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

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    基本几何变换——以鼠标为中心进行缩放
    jquery radio/checkbox change 事件不能触发的问题
    CCF YOCSEF“面向科学的大数据管理与分析”报告会即将举行
    mac iTunes启动失败,声称iTunes文件夹被锁定
    opencv2.3 + visual studio 2010 编译配置方法
    Qt QGLWidget 不能够实时刷新的问题
    在mac os x中建立事件钩子
    二叉树前序、中序、后序、层次遍历
    CRC从原理到实现
    异步FIFO的FPGA实现
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/14243845.html
Copyright © 2011-2022 走看看