mirror of
https://github.com/eiblog/eiblog.git
synced 2026-02-08 15:52:25 +08:00
chore: store mongodb
This commit is contained in:
12
pkg/cache/cache.go
vendored
12
pkg/cache/cache.go
vendored
@@ -8,12 +8,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/eiblog/eiblog/v2/pkg/cache/render"
|
||||
"github.com/eiblog/eiblog/v2/pkg/cache/store"
|
||||
"github.com/eiblog/eiblog/v2/pkg/config"
|
||||
"github.com/eiblog/eiblog/v2/pkg/internal"
|
||||
"github.com/eiblog/eiblog/v2/pkg/model"
|
||||
"github.com/eiblog/eiblog/v2/tools"
|
||||
"github.com/eiblog/eiblog/pkg/cache/render"
|
||||
"github.com/eiblog/eiblog/pkg/cache/store"
|
||||
"github.com/eiblog/eiblog/pkg/config"
|
||||
"github.com/eiblog/eiblog/pkg/internal"
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
"github.com/eiblog/eiblog/tools"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
4
pkg/cache/render/render.go
vendored
4
pkg/cache/render/render.go
vendored
@@ -5,8 +5,8 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/eiblog/eiblog/v2/pkg/config"
|
||||
"github.com/eiblog/eiblog/v2/pkg/model"
|
||||
"github.com/eiblog/eiblog/pkg/config"
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
|
||||
"github.com/eiblog/blackfriday"
|
||||
)
|
||||
|
||||
310
pkg/cache/store/mongodb.go
vendored
310
pkg/cache/store/mongodb.go
vendored
@@ -1,2 +1,312 @@
|
||||
// Package store provides ...
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/eiblog/eiblog/pkg/config"
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
)
|
||||
|
||||
const (
|
||||
mongoDBName = "eiblog"
|
||||
collectionAccount = "account"
|
||||
collectionArticle = "article"
|
||||
collectionBlogger = "blogger"
|
||||
collectionCounter = "counter"
|
||||
collectionSeries = "series"
|
||||
|
||||
counterNameSerie = "serie"
|
||||
counterNameArticle = "article"
|
||||
)
|
||||
|
||||
type mongodb struct {
|
||||
*mongo.Client
|
||||
}
|
||||
|
||||
// Init init mongodb client
|
||||
func (db *mongodb) Init(source string) (Store, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
opts := options.Client().ApplyURI(source)
|
||||
client, err := mongo.Connect(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = client.Ping(ctx, readpref.Primary())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.Client = client
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// LoadInsertAccount 读取或创建账户
|
||||
func (db *mongodb) LoadInsertAccount(ctx context.Context, acct *model.Account) (*model.Account, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionAccount)
|
||||
|
||||
filter := bson.M{"username": config.Conf.BlogApp.Account.Username}
|
||||
result := collection.FindOne(ctx, filter)
|
||||
err := result.Err()
|
||||
if err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
return nil, err
|
||||
}
|
||||
_, err = collection.InsertOne(ctx, acct)
|
||||
} else {
|
||||
err = result.Decode(acct)
|
||||
}
|
||||
return acct, err
|
||||
}
|
||||
|
||||
// LoadInsertBlogger 读取或创建博客
|
||||
func (db *mongodb) LoadInsertBlogger(ctx context.Context, blogger *model.Blogger) (*model.Blogger, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionBlogger)
|
||||
|
||||
filter := bson.M{}
|
||||
result := collection.FindOne(ctx, filter)
|
||||
err := result.Err()
|
||||
if err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
return nil, err
|
||||
}
|
||||
_, err = collection.InsertOne(ctx, blogger)
|
||||
} else {
|
||||
err = result.Decode(blogger)
|
||||
}
|
||||
return blogger, err
|
||||
}
|
||||
|
||||
// LoadAllArticle 读取所有文章
|
||||
func (db *mongodb) LoadAllArticle(ctx context.Context) (model.SortedArticles, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"isdraft": false, "deletetime": bson.M{"$eq": time.Time{}}}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cur.Close(ctx)
|
||||
|
||||
var articles model.SortedArticles
|
||||
for cur.Next(ctx) {
|
||||
article := model.Article{}
|
||||
err = cur.Decode(&article)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
articles = append(articles, &article)
|
||||
}
|
||||
sort.Sort(articles)
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
// LoadTrashArticles 读取回收箱
|
||||
func (db *mongodb) LoadTrashArticles(ctx context.Context) (model.SortedArticles, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"deletetime": bson.M{"$ne": time.Time{}}}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cur.Close(ctx)
|
||||
|
||||
var articles model.SortedArticles
|
||||
for cur.Next(ctx) {
|
||||
article := model.Article{}
|
||||
err = cur.Decode(&article)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
articles = append(articles, &article)
|
||||
}
|
||||
sort.Sort(articles)
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
// LoadDraftArticles 读取草稿箱
|
||||
func (db *mongodb) LoadDraftArticles(ctx context.Context) (model.SortedArticles, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"isdraft": true}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cur.Close(ctx)
|
||||
|
||||
var articles model.SortedArticles
|
||||
for cur.Next(ctx) {
|
||||
article := model.Article{}
|
||||
err = cur.Decode(&article)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
articles = append(articles, &article)
|
||||
}
|
||||
sort.Sort(articles)
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
// InsertSeries 创建专题
|
||||
func (db *mongodb) InsertSeries(ctx context.Context, series *model.Series) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionSeries)
|
||||
|
||||
series.ID = db.nextValue(ctx, counterNameSerie)
|
||||
_, err := collection.InsertOne(ctx, series)
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveSeries 删除专题
|
||||
func (db *mongodb) RemoveSeries(ctx context.Context, id int) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionSeries)
|
||||
|
||||
filter := bson.M{"id": id}
|
||||
_, err := collection.DeleteOne(ctx, filter)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateSeries 更新专题
|
||||
func (db *mongodb) UpdateSeries(ctx context.Context, series *model.Series) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionSeries)
|
||||
|
||||
filter := bson.M{"id": series.ID}
|
||||
update := bson.M{"$set": bson.M{"desc": series.Desc}}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// InsertArticle 创建文章
|
||||
func (db *mongodb) InsertArticle(ctx context.Context, article *model.Article) error {
|
||||
// 分配ID, 占位至起始id
|
||||
for {
|
||||
id := db.nextValue(ctx, counterNameArticle)
|
||||
if id < config.Conf.BlogApp.General.StartID {
|
||||
continue
|
||||
} else {
|
||||
article.ID = id
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
_, err := collection.InsertOne(ctx, article)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteArticle 软删除文章,放入回收箱
|
||||
func (db *mongodb) DeleteArticle(ctx context.Context, id int) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"id": id}
|
||||
update := bson.M{"$set": bson.M{"deletetime": time.Now()}}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveArticle 硬删除文章
|
||||
func (db *mongodb) RemoveArticle(ctx context.Context, id int) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"id": id}
|
||||
_, err := collection.DeleteOne(ctx, filter)
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanArticles 清理回收站文章
|
||||
func (db *mongodb) CleanArticles(ctx context.Context) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
exp := time.Now().Add(time.Duration(config.Conf.BlogApp.General.Trash) * time.Hour)
|
||||
filter := bson.M{"deletetime": bson.M{"$gt": time.Time{}, "$lt": exp}}
|
||||
_, err := collection.DeleteMany(ctx, filter)
|
||||
return err
|
||||
}
|
||||
|
||||
// RecoverArticle 恢复文章到草稿
|
||||
func (db *mongodb) RecoverArticle(ctx context.Context, id int) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
filter := bson.M{"id": id}
|
||||
update := bson.M{"$set": bson.M{"deletetime": time.Time{}, "isdraft": true}}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateAccount 更新账户
|
||||
func (db *mongodb) UpdateAccount(ctx context.Context, name string, fields map[string]interface{}) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionAccount)
|
||||
|
||||
filter := bson.M{"username": name}
|
||||
update := bson.M{}
|
||||
for k, v := range fields {
|
||||
update[k] = v
|
||||
}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateBlogger 更新博客
|
||||
func (db *mongodb) UpdateBlogger(ctx context.Context, fields map[string]interface{}) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionBlogger)
|
||||
|
||||
filter := bson.M{}
|
||||
update := bson.M{}
|
||||
for k, v := range fields {
|
||||
update[k] = v
|
||||
}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateArticle 更新文章
|
||||
func (db *mongodb) UpdateArticle(ctx context.Context, article *model.Article) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionBlogger)
|
||||
|
||||
filter := bson.M{"id": article.ID}
|
||||
update := bson.M{"$set": bson.M{
|
||||
"title": article.Title,
|
||||
"content": article.Content,
|
||||
"updatetime": article.UpdateTime,
|
||||
"createtime": article.CreateTime,
|
||||
}}
|
||||
_, err := collection.UpdateOne(ctx, filter, update)
|
||||
return err
|
||||
}
|
||||
|
||||
// counter counter
|
||||
type counter struct {
|
||||
Name string
|
||||
NextVal int
|
||||
}
|
||||
|
||||
// nextValue counter value
|
||||
func (db *mongodb) nextValue(ctx context.Context, name string) int {
|
||||
collection := db.Database(mongoDBName).Collection(collectionCounter)
|
||||
|
||||
opts := options.FindOneAndUpdate().SetUpsert(true).
|
||||
SetReturnDocument(options.After)
|
||||
filter := bson.M{"name": name}
|
||||
update := bson.M{"$inc": bson.M{"nextval": 1}}
|
||||
|
||||
next := counter{}
|
||||
err := collection.FindOneAndUpdate(ctx, filter, update, opts).Decode(&next)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return next.NextVal
|
||||
}
|
||||
|
||||
// register store
|
||||
func init() {
|
||||
Register("mongodb", &mongodb{})
|
||||
}
|
||||
|
||||
12
pkg/cache/store/mongodb_test.go
vendored
Normal file
12
pkg/cache/store/mongodb_test.go
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// Package store provides ...
|
||||
package store
|
||||
|
||||
var store Store
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
store, err = NewStore("mongodb", "mongodb://127.0.0.1:27017")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
44
pkg/cache/store/store.go
vendored
44
pkg/cache/store/store.go
vendored
@@ -2,11 +2,12 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/eiblog/eiblog/v2/pkg/model"
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -16,14 +17,41 @@ var (
|
||||
|
||||
// Store 存储后端
|
||||
type Store interface {
|
||||
LoadOrCreateAccount(acct *model.Account) (*model.Account, error)
|
||||
LoadOrCreateBlogger(blogger *model.Blogger) (*model.Blogger, error)
|
||||
LoadAllArticles() ([]*model.Article, error)
|
||||
// LoadInsertAccount 读取或创建账户
|
||||
LoadInsertAccount(ctx context.Context, acct *model.Account) (*model.Account, error)
|
||||
// LoadInsertBlogger 读取或创建博客
|
||||
LoadInsertBlogger(ctx context.Context, blogger *model.Blogger) (*model.Blogger, error)
|
||||
// LoadAllArticle 读取所有文章
|
||||
LoadAllArticle(ctx context.Context) (model.SortedArticles, error)
|
||||
// LoadTrashArticles 读取回收箱
|
||||
LoadTrashArticles(ctx context.Context) (model.SortedArticles, error)
|
||||
// LoadDraftArticles 读取草稿箱
|
||||
LoadDraftArticles(ctx context.Context) (model.SortedArticles, error)
|
||||
|
||||
UpdateAccount(name string, fields map[string]interface{}) error
|
||||
UpdateBlogger(fields map[string]interface{}) error
|
||||
UpdateArticle(article *model.Article) error
|
||||
CleanArticles() error
|
||||
// InsertSeries 创建专题
|
||||
InsertSeries(ctx context.Context, series *model.Series) error
|
||||
// RemoveSeries 删除专题
|
||||
RemoveSeries(ctx context.Context, id int) error
|
||||
// UpdateSeries 更新专题
|
||||
UpdateSeries(ctx context.Context, series *model.Series) error
|
||||
|
||||
// InsertArticle 创建文章
|
||||
InsertArticle(ctx context.Context, article *model.Article) error
|
||||
// DeleteArticle 软删除文章,放入回收箱
|
||||
DeleteArticle(ctx context.Context, id int) error
|
||||
// RemoveArticle 硬删除文章
|
||||
RemoveArticle(ctx context.Context, id int) error
|
||||
// CleanArticles 清理回收站文章
|
||||
CleanArticles(ctx context.Context) error
|
||||
// RecoverArticle 恢复文章到草稿
|
||||
RecoverArticle(ctx context.Context, id int) error
|
||||
|
||||
// UpdateAccount 更新账户
|
||||
UpdateAccount(ctx context.Context, name string, fields map[string]interface{}) error
|
||||
// UpdateBlogger 更新博客
|
||||
UpdateBlogger(ctx context.Context, fields map[string]interface{}) error
|
||||
// UpdateArticle 更新文章
|
||||
UpdateArticle(ctx context.Context, article *model.Article) error
|
||||
}
|
||||
|
||||
// Driver 存储驱动
|
||||
|
||||
Reference in New Issue
Block a user