.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) 。
.NET 云原生架构师训练营(模块二 基础巩固 MongoDB API实现)--学习笔记的更多相关文章
- .NET 云原生架构师训练营(权限系统 RGCA 开发任务)--学习笔记
目录 目标 模块拆分 OPM 开发任务 目标 基于上一讲的模块划分做一个任务拆解,根据任务拆解实现功能 模块拆分 模块划分已经完成了边界的划分,边界内外职责清晰 OPM 根据模块拆分画出 OPM(Ob ...
- .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.WebA ...
- .NET 云原生架构师训练营(权限系统 系统演示 ActionAccess)--学习笔记
目录 模块拆分 环境配置 默认用户 ActionAccess 模块拆分 环境配置 mysql migration mysql docker pull mysql docker run -p 3306: ...
- .NET 云原生架构师训练营(权限系统 系统演示 EntityAccess)--学习笔记
目录 模块拆分 EntityAccess 模块拆分 EntityAccess 实体权限 属性权限 实体权限 创建 student https://localhost:7018/Student/dotn ...
- .NET 云原生架构师训练营(权限系统 代码实现 EntityAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(权限系统 代码实现 Identity)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 问答系统)--学习笔记
2.5.6 MongoDB -- 问答系统 MongoDB 数据库设计 API 实现概述 MongoDB 数据库设计 设计优化 内嵌(mongo)还是引用(mysql) 数据一致性 范式:将数据分散到 ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 聚合)--学习笔记
2.5.5 MongoDB -- 聚合 排序 索引类型 创建索引 排序 // 升序 db.getCollection('author').find({}).sort({"age": ...
- .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...
随机推荐
- Jmeter添加事务
事务 通过第三方工具或jmeter代理录制的脚本,你会发现会录制很多的子请求.比如当打开首页后, 会继续打开图片,css,其他请求等资源文件. 通常我们会剔除掉这些子请求, 但如果我需要衡量打开一个页 ...
- flask注册蓝图报错
记录下这个我找了两天的坑... take no arguments() 这两天一直学习flask的时候,我把注册的蓝图,写成注册的form表单的 举个栗子 class TetsView(view.Me ...
- java中的反射(二)
java中的反射(一):https://www.cnblogs.com/KeleLLXin/p/14060555.html 目录 一.反射 1.class类 2.访问字段 3.调用方法 4.调用构造方 ...
- ripple Failed to load resource: the server responded with a status of 404 (Not Found)
在VS2015中使用Cordova + typescript开发中,遇到个问题. 在javascript console 中提示: Failed to load resource: the serve ...
- AtCoder Regular Contest 107(VP)
Contest Link Official Editorial 比赛体验良好,网站全程没有挂.题面简洁好评,题目质量好评.对于我这个蒟蒻来说非常合适的一套题目. A. Simple Math Prob ...
- SQL注入 (一)
一.手工注入 注入点检测 识别方法:通过在url栏输入'.and 1=1.or 1=1.and sleep(1),如果出现报错,或者页面不一致,则可能存在注入点. 注入类型:整数型.字符型.搜索型.B ...
- C++ 虚函数表与多态 —— 多态的简单用法
首先看下边的代码,先创建一个父类,然后在来一个继承父类的子类,两个类中都有自己的 play() 方法,在代码的第35-37行,创建一个父类指针,然后将子类地址引用赋值给父类,这时调用 P 指针的 pl ...
- 从0到1实战移动Web App开发
从0到1实战移动Web App开发 教程介绍 从0到1 实战webapp,通过热门的web前端技术实现移动端app应用,先基础.后实战,在讲解的同时引导思考,会抛出自己独特的观点,一行一行写代码讲 ...
- Redis达到最大占用内存后的淘汰策略
1. 查询Redis最大占用内存 # 查询最大占用内存 config get maxmemory # 为0时在64操作系统中不限制内存,在32位操作系统中最大为3GB 2. Redis设置最大占用内存 ...
- 最全总结 | 聊聊 Python 办公自动化之 PDF(上)
1. 前言 自动化办公,非 Python 莫属! 从本篇文章开始,我们继续聊聊自动化办公中另外一个常用系列:PPT 2. 准备一下 Python 操作 PPT 最强大的依赖库是:python-pptx ...