.NET 云原生架構(gòu)師訓(xùn)練營(模塊二 基礎(chǔ)鞏固 MongoDB API實現(xiàn))--學(xué)習(xí)筆記
2.5.7 MongoDB -- API實現(xiàn)
問題查詢單個實現(xiàn)
問題查詢列表實現(xiàn)
問題跨集合查詢實現(xiàn)
問題創(chuàng)建實現(xiàn)
問題更新實現(xiàn)
問題回答實現(xiàn)
問題評論實現(xiàn)
問題投票實現(xiàn)
回答實現(xiàn)
QuestionController
namespace LighterApi.Controller
{
[ApiController]
[Route("api/[controller]")]
public class QuestionController : ControllerBase
{
private readonly IMongoCollection _questionCollection;
private readonly IMongoCollection _voteCollection;
private readonly IMongoCollection _answerCollection;
public QuestionController(IMongoClient mongoClient)
{
var database = mongoClient.GetDatabase("lighter");
_questionCollection = database.GetCollection("questions");
_voteCollection = database.GetCollection("votes");
_answerCollection = database.GetCollection("answers");
}
}
}
問題查詢單個實現(xiàn)
linq 查詢
[HttpGet]
[Route("{id}")]
public async Task> 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 查詢表達(dá)式
var filter = Builders.Filter.Eq(q => q.Id, id);
await _questionCollection.Find(filter).FirstOrDefaultAsync(cancellationToken);
構(gòu)造空查詢條件的表達(dá)式
var filter = string.IsNullOrEmpty(id)
? Builders.Filter.Empty
: Builders.Filter.Eq(q => q.Id, id);
多段拼接 filter
var filter2 = Builders.Filter.And(filter, Builders.Filter.Eq(q => q.TenantId , "001"));
問題查詢列表實現(xiàn)
數(shù)據(jù) AnyIn查詢
排序 sort : StirngFieldDefinition
分頁 skip, limit
[HttpGet]
public async Task>> 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.Filter.Empty;
if (tags != null && tags.Any())
{
filter = Builders.Filter.AnyIn(q => q.Tags, tags);
}
var sortDefinition = Builders.Sort.Descending(new StringFieldDefinition(sort));
var result = await _questionCollection
.Find(filter)
.Sort(sortDefinition)
.Skip(skip)
.Limit(limit)
.ToListAsync(cancellationToken: cancellationToken);
return Ok(result);
}
問題跨集合查詢實現(xiàn)
[HttpGet]
[Route("{id}/answers")]
public async Task 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);
}
問題創(chuàng)建實現(xiàn)
[HttpPost]
public async Task> 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);
}
問題更新實現(xiàn)
[HttpPatch]
[Route("{id}")]
public async Task UpdateAsync([FromRoute] string id, [FromBody] QuestionUpdateRequest request,
CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(request.Summary))
throw new ArgumentNullException(nameof(request.Summary));
var filter = Builders.Filter.Eq(q => q.Id, id);
var update = Builders.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();
}
使用拼接的方式構(gòu)建表達(dá)式
var updateFieldList = new List>();
if (!string.IsNullOrWhiteSpace(request.Title))
updateFieldList.Add(Builders.Update.Set(q => q.Title, request.Title));
if (!string.IsNullOrWhiteSpace(request.Content))
updateFieldList.Add(Builders.Update.Set(q => q.Content, request.Content));
if (request.Tags != null && request.Tags.Any())
updateFieldList.Add(Builders.Update.Set(q => q.Tags, request.Tags));
updateFieldList.Add(Builders.Update.Push(q => q.Comments,
new Comment {Content = request.Summary, CreatedAt = DateTime.Now}));
var update = Builders.Update.Combine(updateFieldList);
問題回答實現(xiàn)
[HttpPost]
[Route("{id}/answer")]
public async Task> 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.Filter.Eq(q => q.Id, id);
var update = Builders.Update.Push(q => q.Answers, answer.Id);
await _questionCollection.UpdateOneAsync(filter, update, null, cancellationToken);
return Ok();
}
問題評論實現(xiàn)
[HttpPost]
[Route("{id}/comment")]
public async Task CommentAsync([FromRoute] string id, [FromBody] CommentRequest request,
CancellationToken cancellationToken)
{
var filter = Builders.Filter.Eq(q => q.Id, id);
var update = Builders.Update.Push(q => q.Comments,
new Comment {Content = request.Content, CreatedAt = DateTime.Now});
await _questionCollection.UpdateOneAsync(filter, update, null, cancellationToken);
return Ok();
}
問題投票實現(xiàn)
[HttpPost]
[Route("{id}/up")]
public async Task 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.Filter.Eq(q => q.Id, id);
var update = Builders.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 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.Filter.Eq(q => q.Id, id);
var update = Builders.Update.Inc(q => q.VoteCount, -1).AddToSet(q => q.VoteDowns, vote.Id);
await _questionCollection.UpdateOneAsync(filter, update);
return Ok();
}
回答實現(xiàn)
namespace LighterApi.Controller
{
[ApiController]
[Route("api/[controller]")]
public class AnswerController : ControllerBase
{
private readonly IMongoCollection _voteCollection;
private readonly IMongoCollection _answerCollection;
public AnswerController(IMongoClient mongoClient)
{
var database = mongoClient.GetDatabase("lighter");
_voteCollection = database.GetCollection("votes");
_answerCollection = database.GetCollection("answers");
}
[HttpGet]
public async Task> 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 UpdateAsync(string id, string content, string summary,
CancellationToken cancellationToken)
{
var filter = Builders.Filter.Eq(q => q.Id, id);
var update = Builders.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 CommentAsync([FromRoute] string id, [FromBody] CommentRequest request,
CancellationToken cancellationToken)
{
var filter = Builders.Filter.Eq(q => q.Id, id);
var update = Builders.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 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.Filter.Eq(q => q.Id, id);
var update = Builders.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 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.Filter.Eq(q => q.Id, id);
var update = Builders.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
課程鏈接
.NET云原生架構(gòu)師訓(xùn)練營講什么,怎么講,講多久
評論
圖片
表情
