はじめに
WordPressでブログを運用しているのですが、文章を全てMarkdownで保持しておきたいと思い自前でブログシステムを書いています1。1年近く前にWeb屋をリストラされてしまい今は違う仕事をしているので、せっかくなので知らない技術でやってみようとGo(echo)とMongoDBを使って作っています。そこでの経験を書いていければと思います。Goについてはまともに始めて3ヶ月位で、体系的に、というよりは作りながら書籍/ドキュメントを読んでいるので誤りがあれば訂正いただけると幸いです。
開発環境
- Windows10
- Visual Studio Code
- go version go1.15.5 windows/amd64
- MongoDB server version: 4.4.3
- go.mongodb.org/mongo-driver v1.4.5
開発環境はWindowsですが、CentOS7上で動作は確認しています。
MongoDB
use doblog
db.createUser( { user:"USER", pwd:"PASSWORD", roles:[{ "role" : "dbOwner", "db" : "doblog" }] } );
db.entries.createIndex({entryCode: 1},{unique: true});
db.entries.createIndex({entryId: 1},{unique: true});
db.entries.createIndex({isPublished: 1, publishDate: -1});
db.entries.createIndex({category: 1, isPublished: 1, publishDate: -1});
unique:trueでユニークフィールドに。他はfind用。indexが効いているかはexplainでチェック。
db.entries.find({category: "php", isPublished: 1}).sort({publishDate: -1}).limit(1).explain();
参考にしました。 https://qiita.com/koshilife/items/79a8d59fa0973c16de57
WordPressからのデータ移行はphpで書いたのですが省略してます。
mongo-driver
go get -u go.mongodb.org/mongo-driver/mongo
code
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// Entry for get data from mongodb
type Entry struct {
EntryID int32 `bson:"entryId"`
EntryCode string `bson:"entryCode"`
PublishDate string `bson:"publishDate"`
Title string `bson:"title"`
Content string `bson:"content"`
Category []string `bson:"category"`
IsPublished int32 `bson:"isPublished"`
AuthorID int32 `bson:"authorId"`
CreatedAt string `bson:"createdAt"`
UpdatedAt string `bson:"updatedAt"`
}
func main() {
//
// mongodb init
//
ctx := context.Background()
credential := options.Credential{
AuthSource: "doblog",
Username: "USER",
Password: "PASSWORD",
}
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://127.0.0.1:27017").SetAuth(credential))
defer client.Disconnect(ctx)
//
// get entries (publishDateの降順でソート)
//
var entryList []Entry
entries := client.Database("doblog").Collection("entries")
// publishDateの降順
findOption := options.Find().SetSort(bson.D{{Key: "publishDate", Value: -1}})
// PaginatorなどでLimit, Offsetを使いたい場合はこう
// findOption := options.Find().SetSort(bson.D{{Key: "publishDate", Value: -1}}).SetSkip(10).SetLimit(5)
// SQLでの select * from entries where isPublished = 1 と同様
cur, err := entries.Find(ctx, bson.D{{Key: "isPublished", Value: 1}}, findOption)
if err != nil {
fmt.Println(err)
}
defer cur.Close(ctx)
// findはスライス等で返ってこない。 *Cursol型で返ってくるので下記のようにループ回して取得
for cur.Next(ctx) {
var result Entry
err := cur.Decode(&result)
if err != nil {
fmt.Println(err)
}
entryList = append(entryList, result)
}
fmt.Println(entryList)
//
// get entry (entryCodeを指定して一件取得)
//
var entry Entry
err = entries.FindOne(ctx, bson.D{{Key: "entryCode", Value: "net-core-3-0-excel-epplus"}, {Key: "isPublished", Value: 1}}).Decode(&entry)
if err != nil {
fmt.Println(err)
}
fmt.Println(entry)
}
オレオレブログパッケージからコードを抜き出していますが、挙動については確認してから掲載しています。
-
プラグインを使ってMarkdownでpost_contentを書いていたのですが、wp_postを覗いたところ妙なタグで埋め尽くされていたり、魔窟のようになっていたのでこれを機に作ろうかなと。いろいろなプラグインを試したのが悪手だったのかも。 ↩