feat:增加查询博客相邻记录功能

This commit is contained in:
2025-10-12 22:56:31 +08:00
parent 38610aef67
commit 132fbb13b7
8 changed files with 106 additions and 40 deletions

View File

@@ -5,7 +5,8 @@ from sqlalchemy.orm import Session
from config.auth import verify_token from config.auth import verify_token
from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \ from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \
BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate, \
BlogAdjacentResponse
from schemas.blog_elastic import BlogSearch from schemas.blog_elastic import BlogSearch
from schemas.pagination import PageResult from schemas.pagination import PageResult
from config.database import get_db from config.database import get_db
@@ -61,6 +62,11 @@ def delete_blog(blog_id: int, db: Session = Depends(get_db), _=Depends(verify_to
return blog_service.delete_blog(db, blog_id) return blog_service.delete_blog(db, blog_id)
@router.get("/{blog_id}/adjacent", summary="查询相邻博客", response_model=List[BlogAdjacentResponse])
def query_blog_latest(blog_id: int, db: Session = Depends(get_db)):
return blog_service.query_blog_adjacent(db, blog_id)
@router.put("/{blog_id}/comment", summary="新增博客评论", response_model=bool) @router.put("/{blog_id}/comment", summary="新增博客评论", response_model=bool)
def add_blog_comment(blog_id: int, blog_comment: BlogCommentCreate, request: Request, db: Session = Depends(get_db)): def add_blog_comment(blog_id: int, blog_comment: BlogCommentCreate, request: Request, db: Session = Depends(get_db)):
return blog_service.add_blog_comment(db, request, blog_id, blog_comment) return blog_service.add_blog_comment(db, request, blog_id, blog_comment)

View File

@@ -4,7 +4,7 @@ from sqlalchemy.orm import sessionmaker
from config.setting import settings from config.setting import settings
DATABASE_URL = f"mysql+pymysql://{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}" DATABASE_URL = f"mysql+pymysql://root:{settings.DB_PASSWORD}@{settings.DB_HOST}:3306/blog"
engine = create_engine(url=DATABASE_URL, pool_pre_ping=True, pool_recycle=3600) engine = create_engine(url=DATABASE_URL, pool_pre_ping=True, pool_recycle=3600)

View File

@@ -1,15 +1,16 @@
from elasticsearch import Elasticsearch from elasticsearch import Elasticsearch
from config.setting import settings
from schemas.blog_elastic import BLOG_MAPPING from schemas.blog_elastic import BLOG_MAPPING
from config.logging import logger from config.logging import logger
ES_HOSTS = "http://host.docker.internal:9200" ES_HOST = f"http://{settings.ES_HOST}:9200"
ES_USER = "elastic" ES_USER = "elastic"
ES_PASSWORD = "19940822Cxx" ES_PASSWORD = "19940822Cxx"
BLOG_INDEX = "blog" BLOG_INDEX = "blog"
# 注意Python的elasticsearch的版本要和服务器的一致 # 注意Python的elasticsearch的版本要和服务器的一致
es = Elasticsearch(ES_HOSTS, http_auth=(ES_USER, ES_PASSWORD)) es = Elasticsearch(ES_HOST, http_auth=(ES_USER, ES_PASSWORD))
if not es.indices.exists(index=BLOG_INDEX): if not es.indices.exists(index=BLOG_INDEX):
es.indices.create(index=BLOG_INDEX, body=BLOG_MAPPING) es.indices.create(index=BLOG_INDEX, body=BLOG_MAPPING)

View File

@@ -82,7 +82,7 @@ logger.add(
logger.add( logger.add(
log_to_fluent, log_to_fluent,
level="INFO", # 处理 INFO 及以上级别 level=LOG_LEVEL, # 处理 INFO 及以上级别
format="{message}", # 原始消息(实际使用结构化数据) format="{message}", # 原始消息(实际使用结构化数据)
backtrace=True, # 启用堆栈回溯 backtrace=True, # 启用堆栈回溯
diagnose=True # 显示诊断信息 diagnose=True # 显示诊断信息

View File

@@ -2,13 +2,11 @@ from pydantic_settings import BaseSettings
class Settings(BaseSettings): class Settings(BaseSettings):
DB_HOST: str ENVIRONMENT: str
DB_PORT: int
DB_USER: str
DB_PASSWORD: str
DB_NAME: str
LOG_LEVEL: str LOG_LEVEL: str
DB_HOST: str
DB_PASSWORD: str
ES_HOST: str
class Config: class Config:
env_file = ".env" # 指定.env文件路径 env_file = ".env" # 指定.env文件路径

View File

@@ -83,6 +83,14 @@ class BlogLatestResponse(BaseModel):
from_attributes = True from_attributes = True
class BlogAdjacentResponse(BaseModel):
id: int
title: str
class Config:
from_attributes = True
class BlogCommentCreate(BaseModel): class BlogCommentCreate(BaseModel):
parentId: int parentId: int
name: str name: str

View File

@@ -8,11 +8,15 @@ from sqlalchemy import select
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from config.elastic import es, BLOG_INDEX from config.elastic import es, BLOG_INDEX
from config.setting import settings
from models.blog import Blog, BlogCategory, BlogContent from models.blog import Blog, BlogCategory, BlogContent
from schemas.blog_elastic import BlogElastic, BlogSearch from schemas.blog_elastic import BlogElastic, BlogSearch
def sync_all_blog(db: Session) -> bool: def sync_all_blog(db: Session) -> bool:
if settings.ENVIRONMENT == 'dev':
return True
query = select( query = select(
Blog.id, Blog.id,
Blog.title, Blog.title,
@@ -54,6 +58,9 @@ def sync_all_blog(db: Session) -> bool:
def add_blog_elastic(blog: BlogElastic) -> bool: def add_blog_elastic(blog: BlogElastic) -> bool:
if settings.ENVIRONMENT == 'dev':
return True
now = datetime.now() now = datetime.now()
blog.createTime = now.strftime("%Y-%m-%d %H:%M:%S") blog.createTime = now.strftime("%Y-%m-%d %H:%M:%S")
blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S") blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S")
@@ -64,10 +71,14 @@ def add_blog_elastic(blog: BlogElastic) -> bool:
body=blog.model_dump() body=blog.model_dump()
) )
logger.info(f"成功新增博客 {blog.id} 到 Elasticsearch")
return True return True
def update_blog_elastic(blog: BlogElastic) -> bool: def update_blog_elastic(blog: BlogElastic) -> bool:
if settings.ENVIRONMENT == 'dev':
return True
now = datetime.now() now = datetime.now()
blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S") blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S")
@@ -77,12 +88,17 @@ def update_blog_elastic(blog: BlogElastic) -> bool:
body=blog.model_dump() body=blog.model_dump()
) )
logger.info(f"成功修改博客 {blog.id} 到 Elasticsearch")
return True return True
def delete_blog(blog_id: int) -> bool: def delete_blog(blog_id: int) -> bool:
if settings.ENVIRONMENT == 'dev':
return True
es.delete(index=BLOG_INDEX, id=blog_id) es.delete(index=BLOG_INDEX, id=blog_id)
logger.info(f"成功删除博客 {blog_id} 到 Elasticsearch")
return True return True

View File

@@ -1,12 +1,13 @@
from typing import List from typing import List
from fastapi import Request from fastapi import Request
from sqlalchemy import select, func, desc, and_ from sqlalchemy import select, func, desc, and_, asc, delete
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from models.blog import Blog, BlogCategory, BlogVisit, BlogContent, BlogComment from models.blog import Blog, BlogCategory, BlogVisit, BlogContent, BlogComment
from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \ from schemas.blog import BlogResponse, BlogQuery, BlogCategoryResponse, BlogStatsResponse, \
BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate BlogLatestResponse, BlogCommentCreate, BlogCommentResponse, BlogVisitResponse, BlogCreate, BlogUpdate, \
BlogAdjacentResponse
from schemas.blog_elastic import BlogElastic from schemas.blog_elastic import BlogElastic
from schemas.pagination import PageResult from schemas.pagination import PageResult
from schemas.paginate_query import paginate_query from schemas.paginate_query import paginate_query
@@ -82,6 +83,8 @@ def query_blog_by_condition(db: Session, blog_query: BlogQuery) -> List[BlogResp
def query_blog_by_id(db: Session, blog_id: int) -> BlogResponse: def query_blog_by_id(db: Session, blog_id: int) -> BlogResponse:
check_blog_exist(db, blog_id)
query = db.query( query = db.query(
Blog.id.label("id"), Blog.id.label("id"),
Blog.title.label("title"), Blog.title.label("title"),
@@ -104,8 +107,6 @@ def query_blog_by_id(db: Session, blog_id: int) -> BlogResponse:
).filter(Blog.id == blog_id) ).filter(Blog.id == blog_id)
blog = query.first() blog = query.first()
if blog[0] is None:
raise AppException("博客不存在")
return BlogResponse.from_orm(blog) return BlogResponse.from_orm(blog)
@@ -140,7 +141,8 @@ def add_blog(db: Session, blog: BlogCreate) -> bool:
def add_blog_category(db: Session, category: str) -> int: def add_blog_category(db: Session, category: str) -> int:
db_blog_category = db.query(BlogCategory).filter(BlogCategory.name == category).first() db_blog_category = db.execute(select(BlogCategory).where(BlogCategory.name == category)).scalar_one_or_none()
if db_blog_category is None: if db_blog_category is None:
db_new_blog_category = BlogCategory(name=category) db_new_blog_category = BlogCategory(name=category)
db.add(db_new_blog_category) db.add(db_new_blog_category)
@@ -161,9 +163,7 @@ def add_blog_content(db: Session, content: str) -> int:
def update_blog(db: Session, blog_id: int, blog: BlogUpdate) -> bool: def update_blog(db: Session, blog_id: int, blog: BlogUpdate) -> bool:
db_blog = db.query(Blog).filter(Blog.id == blog_id).first() db_blog = check_blog_exist(db, blog_id)
if not db_blog:
raise AppException("博客不存在")
update_data = blog.model_dump(exclude_unset=True) update_data = blog.model_dump(exclude_unset=True)
@@ -186,7 +186,7 @@ def update_blog(db: Session, blog_id: int, blog: BlogUpdate) -> bool:
def update_blog_category(db: Session, category: str) -> int: def update_blog_category(db: Session, category: str) -> int:
db_blog_category = db.query(BlogCategory).filter(BlogCategory.name == category).first() db_blog_category = db.execute(select(BlogCategory).where(BlogCategory.name == category)).scalar_one_or_none()
if db_blog_category is None: if db_blog_category is None:
return add_blog_category(db, category) return add_blog_category(db, category)
@@ -195,12 +195,9 @@ def update_blog_category(db: Session, category: str) -> int:
def update_blog_content(db: Session, blog_content_id: int, blog_content: str) -> bool: def update_blog_content(db: Session, blog_content_id: int, blog_content: str) -> bool:
db_blog_content = db.query(BlogContent).filter(BlogContent.id == blog_content_id).first() db_blog_content = check_blog_content_exist(db, blog_content_id)
if not db_blog_content:
raise AppException("博客内容不存在")
db_blog_content.content = blog_content.encode('utf-8') db_blog_content.content = blog_content.encode('utf-8')
db.commit() db.commit()
db.refresh(db_blog_content) db.refresh(db_blog_content)
@@ -208,24 +205,19 @@ def update_blog_content(db: Session, blog_content_id: int, blog_content: str) ->
def delete_blog(db: Session, blog_id: int) -> bool: def delete_blog(db: Session, blog_id: int) -> bool:
db_blog = db.query(Blog).filter(Blog.id == blog_id).first() db_blog = check_blog_exist(db, blog_id)
if not db_blog:
raise AppException("博客不存在")
delete_blog_content(db, db_blog.content_id) delete_blog_content(db, db_blog.content_id)
db.execute(delete(Blog).where(Blog.id == blog_id))
db.delete(db_blog)
db.commit() db.commit()
return True return True
def delete_blog_content(db: Session, blog_content_id: int) -> bool: def delete_blog_content(db: Session, blog_content_id: int) -> bool:
db_blog_content = db.query(BlogContent).filter(BlogContent.id == blog_content_id).first() check_blog_content_exist(db, blog_content_id)
if not db_blog_content:
raise AppException("博客内容不存在")
db.delete(db_blog_content) db.execute(delete(BlogContent).where(BlogContent.id == blog_content_id))
db.commit() db.commit()
return True return True
@@ -265,6 +257,35 @@ def query_blog_latest(db: Session) -> List[BlogLatestResponse]:
return [BlogLatestResponse.from_orm(result) for result in results] return [BlogLatestResponse.from_orm(result) for result in results]
def query_blog_adjacent(db: Session, blog_id: int) -> List[BlogAdjacentResponse]:
check_blog_exist(db, blog_id)
prev_result = db.execute(
select(Blog.id, Blog.title)
.where(Blog.id < blog_id)
.order_by(desc(Blog.id))
.limit(1)
).first()
next_result = db.execute(
select(Blog.id, Blog.title)
.where(Blog.id > blog_id)
.order_by(asc(Blog.id))
.limit(1)
).first()
return [
BlogAdjacentResponse(
id=prev_result[0] if prev_result else 0,
title=prev_result[1] if prev_result else ""
),
BlogAdjacentResponse(
id=next_result[0] if next_result else 0,
title=next_result[1] if next_result else ""
)
]
def add_blog_visit(db: Session, blog_visit: BlogVisit): def add_blog_visit(db: Session, blog_visit: BlogVisit):
db.add(blog_visit) db.add(blog_visit)
db.commit() db.commit()
@@ -305,15 +326,14 @@ def query_blog_comment(db: Session, blog_id: int) -> List[BlogCommentResponse]:
def add_blog_comment(db: Session, request: Request, blog_id: int, blog_comment: BlogCommentCreate) -> bool: def add_blog_comment(db: Session, request: Request, blog_id: int, blog_comment: BlogCommentCreate) -> bool:
blog = db.query(Blog).filter(Blog.id == blog_id).first() check_blog_exist(db, blog_id)
if not blog:
raise AppException("博客不存在")
if blog_comment.parentId != 0: if blog_comment.parentId != 0:
parent_comment = db.query(BlogComment).filter( parent_comment = db.execute(
BlogComment.id == blog_comment.parentId, select(BlogComment)
BlogComment.blog_id == blog_id .where(BlogComment.id == blog_comment.parentId)
).first() .where(BlogComment.blog_id == blog_id)
).scalar_one_or_none()
if not parent_comment: if not parent_comment:
raise AppException("父评论不存在") raise AppException("父评论不存在")
@@ -334,3 +354,20 @@ def add_blog_comment(db: Session, request: Request, blog_id: int, blog_comment:
db.refresh(db_comment) db.refresh(db_comment)
return True return True
def check_blog_exist(db: Session, blog_id: int) -> Blog:
result = db.execute(select(Blog).where(Blog.id == blog_id)).scalar_one_or_none()
if not result:
raise AppException("博客不存在")
return result
def check_blog_content_exist(db: Session, blog_content_id: int) -> BlogContent:
result = db.execute(select(BlogContent).where(BlogContent.id == blog_content_id)).scalar_one_or_none()
if not result:
raise AppException("博客内容不存在")
return result