From 5f534eeba17987544919f9b105818c0495a66a35 Mon Sep 17 00:00:00 2001
From: zwwhdls
Date: Sun, 22 Dec 2024 22:53:38 +0800
Subject: [PATCH 1/3] feat: search with token
Signed-off-by: zwwhdls
---
go.mod | 11 ++--
go.sum | 22 ++++---
pkg/dispatch/plugin/doc_process.go | 95 ++++++++++++++++++++++++++++++
pkg/dispatch/plugin/header.go | 2 +-
pkg/dispatch/plugin/subcontent.go | 17 ------
pkg/dispatch/plugin/util.go | 38 ++++++++++++
pkg/models/doc/document.go | 3 +
pkg/store/postgres/document.go | 12 +++-
pkg/store/postgres/migrate.go | 18 +++++-
pkg/store/postgres/model.go | 38 ++++++++++++
10 files changed, 223 insertions(+), 33 deletions(-)
create mode 100644 pkg/dispatch/plugin/doc_process.go
create mode 100644 pkg/dispatch/plugin/util.go
diff --git a/go.mod b/go.mod
index 998fe6d..8165d8c 100644
--- a/go.mod
+++ b/go.mod
@@ -7,12 +7,13 @@ toolchain go1.23.3
require (
github.com/PuerkitoBio/goquery v1.10.0
github.com/basenana/go-flow v0.0.0-20230801131009-d05f1f41b706
- github.com/blevesearch/bleve/v2 v2.3.10
+ github.com/blevesearch/bleve/v2 v2.4.0
github.com/blevesearch/upsidedown_store_api v1.0.2
github.com/cdipaolo/goml v0.0.0-20220715001353-00e0c845ae1c
github.com/gin-gonic/gin v1.10.0
github.com/go-gormigrate/gormigrate/v2 v2.1.1
github.com/google/uuid v1.3.0
+ github.com/hyponet/jiebago v0.0.0-20240525141904-e34990856482
github.com/meilisearch/meilisearch-go v0.29.0
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.13.0
@@ -30,12 +31,13 @@ require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
- github.com/blevesearch/bleve_index_api v1.0.6 // indirect
- github.com/blevesearch/geo v0.1.18 // indirect
+ github.com/blevesearch/bleve_index_api v1.1.6 // indirect
+ github.com/blevesearch/geo v0.1.20 // indirect
+ github.com/blevesearch/go-faiss v1.0.13 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/gtreap v0.1.1 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
- github.com/blevesearch/scorch_segment_api/v2 v2.1.6 // indirect
+ github.com/blevesearch/scorch_segment_api/v2 v2.2.9 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/vellum v1.0.10 // indirect
@@ -44,6 +46,7 @@ require (
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
+ github.com/blevesearch/zapx/v16 v16.0.12 // indirect
github.com/bytedance/sonic v1.12.5 // indirect
github.com/bytedance/sonic/loader v0.2.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
diff --git a/go.sum b/go.sum
index 8fd3ad8..ab550f7 100644
--- a/go.sum
+++ b/go.sum
@@ -10,20 +10,22 @@ github.com/basenana/go-flow v0.0.0-20230801131009-d05f1f41b706 h1:FxXoMwMZsufBjS
github.com/basenana/go-flow v0.0.0-20230801131009-d05f1f41b706/go.mod h1:Rs13PWsg/ITdXRiVJcI+yS0iqCfNHxCbIFEt5DCt/RQ=
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
-github.com/blevesearch/bleve/v2 v2.3.10 h1:z8V0wwGoL4rp7nG/O3qVVLYxUqCbEwskMt4iRJsPLgg=
-github.com/blevesearch/bleve/v2 v2.3.10/go.mod h1:RJzeoeHC+vNHsoLR54+crS1HmOWpnH87fL70HAUCzIA=
-github.com/blevesearch/bleve_index_api v1.0.6 h1:gyUUxdsrvmW3jVhhYdCVL6h9dCjNT/geNU7PxGn37p8=
-github.com/blevesearch/bleve_index_api v1.0.6/go.mod h1:YXMDwaXFFXwncRS8UobWs7nvo0DmusriM1nztTlj1ms=
-github.com/blevesearch/geo v0.1.18 h1:Np8jycHTZ5scFe7VEPLrDoHnnb9C4j636ue/CGrhtDw=
-github.com/blevesearch/geo v0.1.18/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM=
+github.com/blevesearch/bleve/v2 v2.4.0 h1:2xyg+Wv60CFHYccXc+moGxbL+8QKT/dZK09AewHgKsg=
+github.com/blevesearch/bleve/v2 v2.4.0/go.mod h1:IhQHoFAbHgWKYavb9rQgQEJJVMuY99cKdQ0wPpst2aY=
+github.com/blevesearch/bleve_index_api v1.1.6 h1:orkqDFCBuNU2oHW9hN2YEJmet+TE9orml3FCGbl1cKk=
+github.com/blevesearch/bleve_index_api v1.1.6/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
+github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
+github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
+github.com/blevesearch/go-faiss v1.0.13 h1:zfFs7ZYD0NqXVSY37j0JZjZT1BhE9AE4peJfcx/NB4A=
+github.com/blevesearch/go-faiss v1.0.13/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
-github.com/blevesearch/scorch_segment_api/v2 v2.1.6 h1:CdekX/Ob6YCYmeHzD72cKpwzBjvkOGegHOqhAkXp6yA=
-github.com/blevesearch/scorch_segment_api/v2 v2.1.6/go.mod h1:nQQYlp51XvoSVxcciBjtvuHPIVjlWrN1hX4qwK2cqdc=
+github.com/blevesearch/scorch_segment_api/v2 v2.2.9 h1:3nBaSBRFokjE4FtPW3eUDgcAu3KphBg1GP07zy/6Uyk=
+github.com/blevesearch/scorch_segment_api/v2 v2.2.9/go.mod h1:ckbeb7knyOOvAdZinn/ASbB7EA3HoagnJkmEV3J7+sg=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
@@ -42,6 +44,8 @@ github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz7
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
+github.com/blevesearch/zapx/v16 v16.0.12 h1:Uccxvjmn+hQ6ywQP+wIiTpdq9LnAviGoryJOmGwAo/I=
+github.com/blevesearch/zapx/v16 v16.0.12/go.mod h1:MYnOshRfSm4C4drxx1LGRI+MVFByykJ2anDY1fxdk9Q=
github.com/bytedance/sonic v1.12.5 h1:hoZxY8uW+mT+OpkcUWw4k0fDINtOcVavEsGfzwzFU/w=
github.com/bytedance/sonic v1.12.5/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@@ -111,6 +115,8 @@ github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8q
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hyponet/jiebago v0.0.0-20240525141904-e34990856482 h1:6phC4CbKBzBQ7PHsf3I21WLF9Fxy8feaLhXmCgh/lcs=
+github.com/hyponet/jiebago v0.0.0-20240525141904-e34990856482/go.mod h1:/QDKR3hYNk0E+DX4XWJHuBsiC1UTGdGynWjps4Kj+T0=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
diff --git a/pkg/dispatch/plugin/doc_process.go b/pkg/dispatch/plugin/doc_process.go
new file mode 100644
index 0000000..d8bcb42
--- /dev/null
+++ b/pkg/dispatch/plugin/doc_process.go
@@ -0,0 +1,95 @@
+/*
+ Copyright 2024 Friday Author.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package plugin
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/PuerkitoBio/goquery"
+ "github.com/hyponet/jiebago"
+
+ "github.com/basenana/friday/pkg/models/doc"
+)
+
+type DocProcessPlugin struct {
+ seg jiebago.Segmenter
+}
+
+func NewDocProcessPlugin() *DocProcessPlugin {
+ seg := jiebago.Segmenter{}
+ seg.LoadDictionary("dict.txt")
+ return &DocProcessPlugin{
+ seg: seg,
+ }
+}
+
+var _ ChainPlugin = &DocProcessPlugin{}
+
+func (s *DocProcessPlugin) Name() string {
+ return "docProcess"
+}
+
+func (s *DocProcessPlugin) Run(ctx context.Context, doc *doc.Document) error {
+ var err error
+ // html analysis
+ doc.PureContent, err = trimContent(doc.Content)
+ if err != nil {
+ return fmt.Errorf("process doc with id %d error: %s", doc.EntryId, err)
+ }
+
+ // split title
+ doc.TitleTokens = s.splitTokens(doc.Name)
+
+ // split content
+ doc.ContentTokens = s.splitTokens(doc.PureContent)
+ return nil
+}
+
+func trimContent(content string) (string, error) {
+ query, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(content)))
+ if err != nil {
+ return "", err
+ }
+
+ query.Find("body").EachWithBreak(func(i int, selection *goquery.Selection) bool {
+ t := strings.TrimSpace(selection.Text())
+ if t != "" {
+ content = t
+ }
+ return true
+ })
+
+ content = ContentTrim("html", content)
+ content = strings.ReplaceAll(content, "'", "")
+ return content, nil
+}
+
+func (s *DocProcessPlugin) splitTokens(content string) []string {
+ contentCh := s.seg.CutForSearch(content, true)
+ tokens := make([]string, 0, len(contentCh))
+ for token := range contentCh {
+ tokens = append(tokens, token)
+ }
+ return tokens
+}
+
+func init() {
+ RegisterPlugin(NewDocProcessPlugin())
+}
diff --git a/pkg/dispatch/plugin/header.go b/pkg/dispatch/plugin/header.go
index 76bf408..a0ccd70 100644
--- a/pkg/dispatch/plugin/header.go
+++ b/pkg/dispatch/plugin/header.go
@@ -39,7 +39,7 @@ func (h *HeaderImgPlugin) Run(ctx context.Context, doc *doc.Document) error {
var headerImgUrl string
query, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(doc.Content)))
if err != nil {
- return fmt.Errorf("build doc query with id %d error: %s", doc.EntryId, err)
+ return fmt.Errorf("get header image of doc with id %d error: %s", doc.EntryId, err)
}
query.Find("img").EachWithBreak(func(i int, selection *goquery.Selection) bool {
diff --git a/pkg/dispatch/plugin/subcontent.go b/pkg/dispatch/plugin/subcontent.go
index 8ae620b..9050173 100644
--- a/pkg/dispatch/plugin/subcontent.go
+++ b/pkg/dispatch/plugin/subcontent.go
@@ -19,7 +19,6 @@ package plugin
import (
"bytes"
"context"
- "regexp"
"strings"
"github.com/PuerkitoBio/goquery"
@@ -41,22 +40,6 @@ func (s *SubContentPlugin) Run(ctx context.Context, doc *doc.Document) error {
var _ ChainPlugin = &SubContentPlugin{}
-var repeatSpace = regexp.MustCompile(`\s+`)
-var htmlCharFilterRegexp = regexp.MustCompile(`?[!\w:]+((\s+[\w-]+(\s*=\s*(?:\\*".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)/?>`)
-
-func ContentTrim(contentType, content string) string {
- switch contentType {
- case "html", "htm", "webarchive", ".webarchive":
- content = strings.ReplaceAll(content, "
", "\n")
- content = strings.ReplaceAll(content, "", "\n")
- content = strings.ReplaceAll(content, "", "\n")
- content = strings.ReplaceAll(content, "", "\n")
- content = htmlCharFilterRegexp.ReplaceAllString(content, "")
- }
- content = repeatSpace.ReplaceAllString(content, " ")
- return content
-}
-
func GenerateContentSubContent(content string) string {
if subContent, err := slowPathContentSubContent([]byte(content)); err == nil {
return subContent
diff --git a/pkg/dispatch/plugin/util.go b/pkg/dispatch/plugin/util.go
new file mode 100644
index 0000000..20c4b1b
--- /dev/null
+++ b/pkg/dispatch/plugin/util.go
@@ -0,0 +1,38 @@
+/*
+ Copyright 2024 Friday Author.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package plugin
+
+import (
+ "regexp"
+ "strings"
+)
+
+var repeatSpace = regexp.MustCompile(`\s+`)
+var htmlCharFilterRegexp = regexp.MustCompile(`?[!\w:]+((\s+[\w-]+(\s*=\s*(?:\\*".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)/?>`)
+
+func ContentTrim(contentType, content string) string {
+ switch contentType {
+ case "html", "htm", "webarchive", ".webarchive":
+ content = strings.ReplaceAll(content, "", "\n")
+ content = strings.ReplaceAll(content, "", "\n")
+ content = strings.ReplaceAll(content, "", "\n")
+ content = strings.ReplaceAll(content, "", "\n")
+ content = htmlCharFilterRegexp.ReplaceAllString(content, "")
+ }
+ content = repeatSpace.ReplaceAllString(content, " ")
+ return content
+}
diff --git a/pkg/models/doc/document.go b/pkg/models/doc/document.go
index ccdb588..ab07a19 100644
--- a/pkg/models/doc/document.go
+++ b/pkg/models/doc/document.go
@@ -35,6 +35,9 @@ type Document struct {
WebUrl string `json:"web_url,omitempty"`
HeaderImage string `json:"header_image,omitempty"`
SubContent string `json:"sub_content,omitempty"`
+ PureContent string `json:"pure_content,omitempty"`
+ TitleTokens []string `json:"title_tokens,omitempty"`
+ ContentTokens []string `json:"content_tokens,omitempty"`
Marked *bool `json:"marked,omitempty"`
Unread *bool `json:"unread,omitempty"`
CreatedAt time.Time `json:"created_at"`
diff --git a/pkg/store/postgres/document.go b/pkg/store/postgres/document.go
index 92d1b76..387098e 100644
--- a/pkg/store/postgres/document.go
+++ b/pkg/store/postgres/document.go
@@ -40,6 +40,14 @@ func (p *PostgresClient) CreateDocument(ctx context.Context, doc *doc.Document)
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
docMod = docMod.From(doc)
res = tx.Create(docMod)
+ if res.Error != nil {
+ return res.Error
+ }
+
+ // update tokens
+ docMod = docMod.Tokens(doc)
+ p.log.Info("update token", docMod.Token)
+ res = tx.Model(&Document{}).Where("id = ?", docMod.ID).Update("token", gorm.Expr(string(docMod.Token)))
return res.Error
}
return res.Error
@@ -144,7 +152,9 @@ func docQueryFilter(tx *gorm.DB, filter *doc.DocumentFilter) *gorm.DB {
tx = tx.Where("document.name LIKE ?", "%"+filter.FuzzyName+"%")
}
if filter.Search != "" {
- tx = tx.Where("document.content LIKE ?", "%"+filter.Search+"%")
+ tx = tx.Where("document.token @@ to_tsquery('simple', ?)", filter.Search).
+ Select("*, ts_rank(document.token, to_tsquery('simple', ?)) as rank", filter.Search).
+ Order("rank DESC")
}
return tx
}
diff --git a/pkg/store/postgres/migrate.go b/pkg/store/postgres/migrate.go
index 98bbe18..bbe48c9 100644
--- a/pkg/store/postgres/migrate.go
+++ b/pkg/store/postgres/migrate.go
@@ -59,8 +59,22 @@ func buildMigrations() []*gormigrate.Migration {
if err != nil {
return err
}
- //_ = db.Exec(`CREATE INDEX name ON table USING gist(content);`)
- //_ = db.Exec("CREATE INDEX idx_doc_content ON document USING GIN (content gin_trgm_ops);")
+ return nil
+ },
+ Rollback: func(db *gorm.DB) error {
+ return nil
+ },
+ },
+ {
+ ID: "2024122201",
+ Migrate: func(db *gorm.DB) error {
+ err := db.AutoMigrate(
+ &Document{},
+ )
+ if err != nil {
+ return err
+ }
+ _ = db.Exec("CREATE INDEX idx_document_token ON public.document USING gin (token);")
return nil
},
Rollback: func(db *gorm.DB) error {
diff --git a/pkg/store/postgres/model.go b/pkg/store/postgres/model.go
index fa48e00..5f401a3 100644
--- a/pkg/store/postgres/model.go
+++ b/pkg/store/postgres/model.go
@@ -17,7 +17,10 @@
package postgres
import (
+ "database/sql/driver"
"encoding/json"
+ "fmt"
+ "strings"
"time"
"github.com/basenana/friday/pkg/models/doc"
@@ -114,6 +117,28 @@ func (v *BleveKV) TableName() string {
return "friday_blevekv"
}
+type TsVector string
+
+func (t *TsVector) Scan(value interface{}) error {
+ if value == nil {
+ *t = ""
+ return nil
+ }
+ switch v := value.(type) {
+ case []byte:
+ *t = TsVector(v)
+ case string:
+ *t = TsVector(v)
+ default:
+ return fmt.Errorf("cannot scan type %T into TsVector", value)
+ }
+ return nil
+}
+
+func (t *TsVector) Value() (driver.Value, error) {
+ return string(*t), nil
+}
+
type Document struct {
ID int64 `gorm:"column:id;primaryKey"`
OID int64 `gorm:"column:oid;index:doc_oid"`
@@ -126,8 +151,10 @@ type Document struct {
Summary string `gorm:"column:summary"`
HeaderImage string `gorm:"column:header_image"`
SubContent string `gorm:"column:sub_content"`
+ PureContent string `gorm:"column:pure_content"`
Marked bool `gorm:"column:marked;index:doc_is_marked"`
Unread bool `gorm:"column:unread;index:doc_is_unread"`
+ Token TsVector `gorm:"column:token;type:tsvector"`
CreatedAt time.Time `gorm:"column:created_at"`
ChangedAt time.Time `gorm:"column:changed_at"`
}
@@ -154,10 +181,21 @@ func (d *Document) From(document *doc.Document) *Document {
d.Unread = *document.Unread
}
d.HeaderImage = document.HeaderImage
+ d.PureContent = document.PureContent
d.SubContent = document.SubContent
return d
}
+func (d *Document) Tokens(document *doc.Document) *Document {
+ d.Token = TsVector(
+ fmt.Sprintf("setweight(to_tsvector('simple', '%s'), 'A') || setweight(to_tsvector('simple', '%s'), 'B')",
+ strings.Join(document.TitleTokens, " "),
+ strings.Join(document.ContentTokens, " "),
+ ),
+ )
+ return d
+}
+
func (d *Document) UpdateFrom(document *doc.Document) *Document {
if document.Unread != nil {
d.Unread = *document.Unread
From 09756143ee34159f513ff47be5b1b4cdc0507ed4 Mon Sep 17 00:00:00 2001
From: zwwhdls
Date: Tue, 24 Dec 2024 21:07:50 +0800
Subject: [PATCH 2/3] add unittest
Signed-off-by: zwwhdls
---
go.mod | 10 ++-
go.sum | 19 ++++++
pkg/service/chain.go | 9 ++-
pkg/service/chain_test.go | 8 ++-
pkg/store/{postgres => db}/migrate.go | 4 +-
pkg/store/{postgres => db}/model.go | 4 +-
pkg/store/interface.go | 1 +
pkg/store/meili/meili.go | 4 ++
pkg/store/meili/mock.go | 4 ++
pkg/store/memory/memory.go | 98 +++++++++++++++++++++++++++
pkg/store/postgres/bleve.go | 26 +++----
pkg/store/postgres/document.go | 61 ++++++++++-------
pkg/store/postgres/postgres.go | 10 +--
pkg/store/postgres/vector.go | 19 +++---
14 files changed, 219 insertions(+), 58 deletions(-)
rename pkg/store/{postgres => db}/migrate.go (97%)
rename pkg/store/{postgres => db}/model.go (99%)
create mode 100644 pkg/store/memory/memory.go
diff --git a/go.mod b/go.mod
index 8165d8c..a85b3d6 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,7 @@ require (
go.uber.org/zap v1.27.0
golang.org/x/time v0.4.0
gorm.io/driver/postgres v1.5.2
- gorm.io/gorm v1.25.4
+ gorm.io/gorm v1.25.7
)
require (
@@ -51,9 +51,12 @@ require (
github.com/bytedance/sonic/loader v0.2.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
+ github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/glebarez/go-sqlite v1.21.2 // indirect
+ github.com/glebarez/sqlite v1.11.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -84,6 +87,7 @@ require (
github.com/mschoch/smat v0.2.0 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@@ -100,4 +104,8 @@ require (
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+ modernc.org/libc v1.22.5 // indirect
+ modernc.org/mathutil v1.5.0 // indirect
+ modernc.org/memory v1.5.0 // indirect
+ modernc.org/sqlite v1.23.1 // indirect
)
diff --git a/go.sum b/go.sum
index ab550f7..5623244 100644
--- a/go.sum
+++ b/go.sum
@@ -61,6 +61,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -70,6 +72,10 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
+github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
+github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
+github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-gormigrate/gormigrate/v2 v2.1.1 h1:eGS0WTFRV30r103lU8JNXY27KbviRnqqIDobW3EV3iY=
github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kRCk+E3UbV2f5gv+1ndLc=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
@@ -177,6 +183,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/rueidis v1.0.0 h1:LrUhkD46Es7neMvpTgqyYGRpvlGG4F6dLIRq+nUw/ho=
github.com/redis/rueidis v1.0.0/go.mod h1:yxbpgX+VYNxCvdE0KEQXDeUFcF2hB2Oz/TJiaqFxoEU=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -308,4 +317,14 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
+gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
+modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
+modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
+modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
+modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
+modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
+modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
diff --git a/pkg/service/chain.go b/pkg/service/chain.go
index 64d9d9d..217ba60 100644
--- a/pkg/service/chain.go
+++ b/pkg/service/chain.go
@@ -93,7 +93,11 @@ func (c *Chain) CreateDocument(ctx context.Context, document *doc.Document) erro
}
}
c.Log.Debugf("create document: %+v", document.Name)
- return c.DocClient.CreateDocument(ctx, document)
+ if err := c.DocClient.CreateDocument(ctx, document); err != nil {
+ c.Log.Errorf("create document error: %s", err)
+ return err
+ }
+ return c.DocClient.UpdateTokens(ctx, document)
})
}
@@ -110,6 +114,9 @@ func (c *Chain) GetDocument(ctx context.Context, namespace string, entryId int64
ctx = c.WithNamespace(ctx, namespace)
doc, err := c.DocClient.GetDocument(ctx, entryId)
if err != nil {
+ if err == models.ErrNotFound {
+ return nil, nil
+ }
c.Log.Errorf("get document error: %s", err)
return nil, err
}
diff --git a/pkg/service/chain_test.go b/pkg/service/chain_test.go
index cce87b5..677cdbf 100644
--- a/pkg/service/chain_test.go
+++ b/pkg/service/chain_test.go
@@ -28,7 +28,7 @@ import (
_ "github.com/basenana/friday/pkg/dispatch/plugin"
"github.com/basenana/friday/pkg/models/doc"
"github.com/basenana/friday/pkg/service"
- "github.com/basenana/friday/pkg/store/meili"
+ "github.com/basenana/friday/pkg/store/memory"
"github.com/basenana/friday/pkg/utils/logger"
)
@@ -49,8 +49,10 @@ var _ = Describe("Chain", func() {
BeforeEach(func() {
service.ChainPool = dispatch.NewPool(10)
logger.InitLog()
+ client, err := memory.NewMemoryMetaStore()
+ Expect(err).Should(BeNil())
Chain = &service.Chain{
- DocClient: &meili.MockClient{},
+ DocClient: client,
Plugins: []plugin.ChainPlugin{},
Log: logger.NewLog("test"),
}
@@ -84,7 +86,7 @@ var _ = Describe("Chain", func() {
CreatedAt: t,
ChangedAt: t,
}
- err := Chain.CreateDocument(context.TODO(), doc11)
+ err = Chain.CreateDocument(context.TODO(), doc11)
Expect(err).Should(BeNil())
err = Chain.CreateDocument(context.TODO(), doc12)
Expect(err).Should(BeNil())
diff --git a/pkg/store/postgres/migrate.go b/pkg/store/db/migrate.go
similarity index 97%
rename from pkg/store/postgres/migrate.go
rename to pkg/store/db/migrate.go
index bbe48c9..3bd1094 100644
--- a/pkg/store/postgres/migrate.go
+++ b/pkg/store/db/migrate.go
@@ -1,5 +1,5 @@
/*
- Copyright 2023 Friday Author.
+ Copyright 2024 Friday Author.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
limitations under the License.
*/
-package postgres
+package db
import (
"github.com/go-gormigrate/gormigrate/v2"
diff --git a/pkg/store/postgres/model.go b/pkg/store/db/model.go
similarity index 99%
rename from pkg/store/postgres/model.go
rename to pkg/store/db/model.go
index 5f401a3..ee97461 100644
--- a/pkg/store/postgres/model.go
+++ b/pkg/store/db/model.go
@@ -1,5 +1,5 @@
/*
- Copyright 2023 Friday Author.
+ Copyright 2024 Friday Author.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
limitations under the License.
*/
-package postgres
+package db
import (
"database/sql/driver"
diff --git a/pkg/store/interface.go b/pkg/store/interface.go
index 138bf7b..c002a0a 100644
--- a/pkg/store/interface.go
+++ b/pkg/store/interface.go
@@ -31,6 +31,7 @@ type VectorStore interface {
type DocStoreInterface interface {
CreateDocument(ctx context.Context, doc *doc.Document) error
+ UpdateTokens(ctx context.Context, doc *doc.Document) error
UpdateDocument(ctx context.Context, doc *doc.Document) error
GetDocument(ctx context.Context, entryId int64) (*doc.Document, error)
FilterDocuments(ctx context.Context, filter *doc.DocumentFilter) ([]*doc.Document, error)
diff --git a/pkg/store/meili/meili.go b/pkg/store/meili/meili.go
index 5f421e5..93320e4 100644
--- a/pkg/store/meili/meili.go
+++ b/pkg/store/meili/meili.go
@@ -155,6 +155,10 @@ func (c *Client) CreateDocument(ctx context.Context, doc *doc.Document) error {
return nil
}
+func (c *Client) UpdateTokens(ctx context.Context, doc *doc.Document) error {
+ return nil
+}
+
func (c *Client) UpdateDocument(ctx context.Context, doc *doc.Document) error {
// delete document attr
newAttrsQuery := (&DocumentAttrQuery{}).FromModel(doc)
diff --git a/pkg/store/meili/mock.go b/pkg/store/meili/mock.go
index b0f3b21..558574e 100644
--- a/pkg/store/meili/mock.go
+++ b/pkg/store/meili/mock.go
@@ -40,6 +40,10 @@ func (m *MockClient) CreateDocument(ctx context.Context, doc *doc.Document) erro
return nil
}
+func (m *MockClient) UpdateTokens(ctx context.Context, doc *doc.Document) error {
+ return nil
+}
+
func (m *MockClient) UpdateDocument(ctx context.Context, doc *doc.Document) error {
aq := (&DocumentAttrQuery{}).FromModel(doc)
result := []*DocumentAttr{}
diff --git a/pkg/store/memory/memory.go b/pkg/store/memory/memory.go
new file mode 100644
index 0000000..5cba58f
--- /dev/null
+++ b/pkg/store/memory/memory.go
@@ -0,0 +1,98 @@
+/*
+ Copyright 2024 Friday Author.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package memory
+
+import (
+ "context"
+ "time"
+
+ "github.com/glebarez/sqlite"
+ "go.uber.org/zap"
+ "gorm.io/gorm"
+
+ "github.com/basenana/friday/pkg/models/doc"
+ "github.com/basenana/friday/pkg/store"
+ "github.com/basenana/friday/pkg/store/db"
+ "github.com/basenana/friday/pkg/store/postgres"
+ "github.com/basenana/friday/pkg/store/utils"
+ "github.com/basenana/friday/pkg/utils/logger"
+)
+
+type MemoryClient struct {
+ log *zap.SugaredLogger
+ dbStore postgres.PostgresClient
+}
+
+var _ store.DocStoreInterface = &MemoryClient{}
+
+func NewMemoryMetaStore() (*MemoryClient, error) {
+ log := logger.NewLog("memory")
+ dbEntity, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: utils.NewDbLogger()})
+ if err != nil {
+ return nil, err
+ }
+
+ dbConn, err := dbEntity.DB()
+ if err != nil {
+ return nil, err
+ }
+
+ if err = dbConn.Ping(); err != nil {
+ return nil, err
+ }
+
+ dbConn.SetMaxIdleConns(1)
+ dbConn.SetMaxOpenConns(1)
+ dbConn.SetConnMaxLifetime(time.Hour)
+
+ dbEnt, err := db.NewDbEntity(dbEntity, db.Migrate)
+ if err != nil {
+ return nil, err
+ }
+
+ return &MemoryClient{
+ dbStore: postgres.PostgresClient{
+ Logger: log,
+ DEntity: dbEnt,
+ },
+ }, nil
+}
+
+func (m *MemoryClient) CreateDocument(ctx context.Context, doc *doc.Document) error {
+ return m.dbStore.CreateDocument(ctx, doc)
+}
+
+func (m *MemoryClient) UpdateTokens(ctx context.Context, doc *doc.Document) error {
+ return nil
+}
+
+func (m *MemoryClient) UpdateDocument(ctx context.Context, doc *doc.Document) error {
+ return m.dbStore.UpdateDocument(ctx, doc)
+}
+
+func (m *MemoryClient) GetDocument(ctx context.Context, entryId int64) (*doc.Document, error) {
+ return m.dbStore.GetDocument(ctx, entryId)
+}
+
+func (m *MemoryClient) FilterDocuments(ctx context.Context, filter *doc.DocumentFilter) ([]*doc.Document, error) {
+ filter.Search = ""
+ return m.dbStore.FilterDocuments(ctx, filter)
+}
+
+func (m *MemoryClient) DeleteDocument(ctx context.Context, docId int64) error {
+ return m.dbStore.DeleteDocument(ctx, docId)
+}
diff --git a/pkg/store/postgres/bleve.go b/pkg/store/postgres/bleve.go
index 2e6b576..d75ca09 100644
--- a/pkg/store/postgres/bleve.go
+++ b/pkg/store/postgres/bleve.go
@@ -9,6 +9,8 @@ import (
"github.com/blevesearch/bleve/v2/registry"
"github.com/blevesearch/upsidedown_store_api"
"gorm.io/gorm"
+
+ "github.com/basenana/friday/pkg/store/db"
)
const (
@@ -75,9 +77,9 @@ func (p *PgKVWriter) ExecuteBatch(batch store.KVBatch) error {
return fmt.Errorf("wrong type of batch")
}
- err := p.dEntity.DB.WithContext(context.Background()).Transaction(func(tx *gorm.DB) error {
+ err := p.DEntity.DB.WithContext(context.Background()).Transaction(func(tx *gorm.DB) error {
for k, mergeOps := range emulatedBatch.Merger.Merges {
- mod := &BleveKV{ID: bytes2Str([]byte(k)), Key: []byte(k)}
+ mod := &db.BleveKV{ID: bytes2Str([]byte(k)), Key: []byte(k)}
res := tx.First(mod)
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
@@ -99,7 +101,7 @@ func (p *PgKVWriter) ExecuteBatch(batch store.KVBatch) error {
}
for _, op := range emulatedBatch.Ops {
- mod := &BleveKV{ID: bytes2Str(op.K), Key: op.K, Value: op.V}
+ mod := &db.BleveKV{ID: bytes2Str(op.K), Key: op.K, Value: op.V}
var res *gorm.DB
if op.V != nil {
res = tx.Save(mod)
@@ -127,8 +129,8 @@ type PgKVReader struct {
var _ store.KVReader = &PgKVReader{}
func (p *PgKVReader) Get(key []byte) ([]byte, error) {
- mod := &BleveKV{ID: bytes2Str(key)}
- res := p.dEntity.DB.WithContext(context.Background()).First(mod)
+ mod := &db.BleveKV{ID: bytes2Str(key)}
+ res := p.DEntity.DB.WithContext(context.Background()).First(mod)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return nil, nil
@@ -144,8 +146,8 @@ func (p *PgKVReader) MultiGet(keys [][]byte) ([][]byte, error) {
idList[i] = bytes2Str(k)
}
- var modList []BleveKV
- res := p.dEntity.DB.WithContext(context.Background()).Where("id IN ?", idList).Find(modList)
+ var modList []db.BleveKV
+ res := p.DEntity.DB.WithContext(context.Background()).Where("id IN ?", idList).Find(modList)
if res.Error != nil {
return nil, res.Error
}
@@ -157,8 +159,8 @@ func (p *PgKVReader) MultiGet(keys [][]byte) ([][]byte, error) {
}
func (p *PgKVReader) PrefixIterator(prefix []byte) store.KVIterator {
- var modList []BleveKV
- res := p.PostgresClient.dEntity.WithContext(context.Background()).
+ var modList []db.BleveKV
+ res := p.PostgresClient.DEntity.WithContext(context.Background()).
Where("id LIKE ?", bytes2Str(prefix)+"%").
Order("key DESC").Find(&modList)
if res.Error != nil {
@@ -175,8 +177,8 @@ func (p *PgKVReader) PrefixIterator(prefix []byte) store.KVIterator {
}
func (p *PgKVReader) RangeIterator(start, end []byte) store.KVIterator {
- var modList []BleveKV
- res := p.PostgresClient.dEntity.WithContext(context.Background()).
+ var modList []db.BleveKV
+ res := p.PostgresClient.DEntity.WithContext(context.Background()).
Where("id >= ? AND id < ?", bytes2Str(start), bytes2Str(end)).
Order("key DESC").Find(&modList)
if res.Error != nil {
@@ -201,7 +203,7 @@ func NewPgKVReader(cli *PostgresClient) *PgKVReader {
}
type KVIterator struct {
- listKV []BleveKV
+ listKV []db.BleveKV
start, end []byte
prefix []byte
crt int
diff --git a/pkg/store/postgres/document.go b/pkg/store/postgres/document.go
index 387098e..187d086 100644
--- a/pkg/store/postgres/document.go
+++ b/pkg/store/postgres/document.go
@@ -26,15 +26,16 @@ import (
"github.com/basenana/friday/pkg/models"
"github.com/basenana/friday/pkg/models/doc"
"github.com/basenana/friday/pkg/store"
+ "github.com/basenana/friday/pkg/store/db"
"github.com/basenana/friday/pkg/store/utils"
)
var _ store.DocStoreInterface = &PostgresClient{}
func (p *PostgresClient) CreateDocument(ctx context.Context, doc *doc.Document) error {
- defer trace.StartRegion(ctx, "metastore.sql.SaveDocument").End()
- err := p.dEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
- docMod := &Document{}
+ defer trace.StartRegion(ctx, "store.doc.CreateDocument").End()
+ err := p.DEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ docMod := &db.Document{}
res := tx.Where("oid = ?", doc.EntryId).First(docMod)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
@@ -44,11 +45,6 @@ func (p *PostgresClient) CreateDocument(ctx context.Context, doc *doc.Document)
return res.Error
}
- // update tokens
- docMod = docMod.Tokens(doc)
- p.log.Info("update token", docMod.Token)
- res = tx.Model(&Document{}).Where("id = ?", docMod.ID).Update("token", gorm.Expr(string(docMod.Token)))
- return res.Error
}
return res.Error
}
@@ -62,10 +58,29 @@ func (p *PostgresClient) CreateDocument(ctx context.Context, doc *doc.Document)
return nil
}
+func (p *PostgresClient) UpdateTokens(ctx context.Context, doc *doc.Document) error {
+ defer trace.StartRegion(ctx, "store.doc.UpdateTokens").End()
+ err := p.DEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ docMod := &db.Document{}
+ res := tx.Where("oid = ?", doc.EntryId).First(docMod)
+ if res.Error != nil {
+ return res.Error
+ }
+ docMod = docMod.Tokens(doc)
+ p.Logger.Info("update token", docMod.Token)
+ res = tx.Model(&db.Document{}).Where("id = ?", docMod.ID).Update("token", gorm.Expr(string(docMod.Token)))
+ return res.Error
+ })
+ if err != nil {
+ return utils.SqlError2Error(err)
+ }
+ return nil
+}
+
func (p *PostgresClient) UpdateDocument(ctx context.Context, doc *doc.Document) error {
- defer trace.StartRegion(ctx, "metastore.sql.SaveDocument").End()
- err := p.dEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
- docMod := &Document{}
+ defer trace.StartRegion(ctx, "store.doc.UpdateDocument").End()
+ err := p.DEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ docMod := &db.Document{}
res := tx.Where("oid = ?", doc.EntryId).First(docMod)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
@@ -86,9 +101,9 @@ func (p *PostgresClient) UpdateDocument(ctx context.Context, doc *doc.Document)
}
func (p *PostgresClient) GetDocument(ctx context.Context, entryId int64) (*doc.Document, error) {
- defer trace.StartRegion(ctx, "metastore.sql.GetDocument").End()
- doc := &Document{}
- res := p.dEntity.WithNamespace(ctx).Where("oid = ?", entryId).First(doc)
+ defer trace.StartRegion(ctx, "store.doc.GetDocument").End()
+ doc := &db.Document{}
+ res := p.DEntity.WithNamespace(ctx).Where("oid = ?", entryId).First(doc)
if res.Error != nil {
return nil, utils.SqlError2Error(res.Error)
}
@@ -96,13 +111,13 @@ func (p *PostgresClient) GetDocument(ctx context.Context, entryId int64) (*doc.D
}
func (p *PostgresClient) FilterDocuments(ctx context.Context, filter *doc.DocumentFilter) ([]*doc.Document, error) {
- defer trace.StartRegion(ctx, "metastore.sql.ListDocument").End()
- docList := make([]Document, 0)
+ defer trace.StartRegion(ctx, "store.doc.FilterDocuments").End()
+ docList := make([]db.Document, 0)
q := p.WithNamespace(ctx)
if page := models.GetPagination(ctx); page != nil {
q = q.Offset(page.Offset()).Limit(page.Limit())
}
- res := docOrder(docQueryFilter(q, filter), &filter.Order).Find(&docList)
+ res := docOrder(p.docQueryFilter(q, filter), &filter.Order).Find(&docList)
if res.Error != nil {
return nil, utils.SqlError2Error(res.Error)
}
@@ -115,15 +130,15 @@ func (p *PostgresClient) FilterDocuments(ctx context.Context, filter *doc.Docume
}
func (p *PostgresClient) DeleteDocument(ctx context.Context, entryId int64) error {
- defer trace.StartRegion(ctx, "metastore.sql.DeleteDocument").End()
- err := p.dEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
- res := namespaceQuery(ctx, tx).Where("oid = ?", entryId).Delete(&Document{})
+ defer trace.StartRegion(ctx, "store.doc.DeleteDocument").End()
+ err := p.DEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ res := namespaceQuery(ctx, tx).Where("oid = ?", entryId).Delete(&db.Document{})
return res.Error
})
return utils.SqlError2Error(err)
}
-func docQueryFilter(tx *gorm.DB, filter *doc.DocumentFilter) *gorm.DB {
+func (p *PostgresClient) docQueryFilter(tx *gorm.DB, filter *doc.DocumentFilter) *gorm.DB {
if filter.ParentID != nil {
tx = tx.Where("document.parent_entry_id = ?", filter.ParentID)
}
@@ -183,7 +198,7 @@ func namespaceQuery(ctx context.Context, tx *gorm.DB) *gorm.DB {
func (p *PostgresClient) WithNamespace(ctx context.Context) *gorm.DB {
ns := models.GetNamespace(ctx)
if ns.String() == models.DefaultNamespaceValue {
- return p.dEntity.WithContext(ctx)
+ return p.DEntity.WithContext(ctx)
}
- return p.dEntity.WithContext(ctx).Where("namespace = ?", ns.String())
+ return p.DEntity.WithContext(ctx).Where("namespace = ?", ns.String())
}
diff --git a/pkg/store/postgres/postgres.go b/pkg/store/postgres/postgres.go
index 661ca0c..ae5ef08 100644
--- a/pkg/store/postgres/postgres.go
+++ b/pkg/store/postgres/postgres.go
@@ -31,8 +31,8 @@ import (
const defaultNamespace = "global"
type PostgresClient struct {
- log *zap.SugaredLogger
- dEntity *db.Entity
+ Logger *zap.SugaredLogger
+ DEntity *db.Entity
}
func NewPostgresClient(postgresUrl string) (*PostgresClient, error) {
@@ -55,13 +55,13 @@ func NewPostgresClient(postgresUrl string) (*PostgresClient, error) {
return nil, err
}
- dbEnt, err := db.NewDbEntity(dbObj, Migrate)
+ dbEnt, err := db.NewDbEntity(dbObj, db.Migrate)
if err != nil {
return nil, err
}
return &PostgresClient{
- log: log,
- dEntity: dbEnt,
+ Logger: log,
+ DEntity: dbEnt,
}, nil
}
diff --git a/pkg/store/postgres/vector.go b/pkg/store/postgres/vector.go
index 9d5f367..1aa607c 100644
--- a/pkg/store/postgres/vector.go
+++ b/pkg/store/postgres/vector.go
@@ -28,6 +28,7 @@ import (
"github.com/basenana/friday/pkg/models/vector"
"github.com/basenana/friday/pkg/store"
+ "github.com/basenana/friday/pkg/store/db"
"github.com/basenana/friday/pkg/utils"
)
@@ -36,7 +37,7 @@ func (p *PostgresClient) Store(ctx context.Context, element *vector.Element, ext
if namespace == nil {
namespace = defaultNamespace
}
- return p.dEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+ return p.DEntity.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if extra == nil {
extra = make(map[string]interface{})
}
@@ -48,7 +49,7 @@ func (p *PostgresClient) Store(ctx context.Context, element *vector.Element, ext
return err
}
- var v *Index
+ var v *db.Index
v, err = v.From(element)
if err != nil {
return err
@@ -57,7 +58,7 @@ func (p *PostgresClient) Store(ctx context.Context, element *vector.Element, ext
v.Extra = string(b)
v.Namespace = namespace.(string)
- vModel := &Index{}
+ vModel := &db.Index{}
res := tx.Where("namespace = ? AND name = ? AND idx_group = ?", namespace, element.Name, element.Group).First(vModel)
if res.Error != nil && res.Error != gorm.ErrRecordNotFound {
return res.Error
@@ -91,9 +92,9 @@ func (p *PostgresClient) Search(ctx context.Context, query vector.VectorDocQuery
vectors64 = append(vectors64, float64(v))
}
// query from db
- existIndexes := make([]Index, 0)
+ existIndexes := make([]db.Index, 0)
- res := p.dEntity.WithNamespace(ctx)
+ res := p.DEntity.WithNamespace(ctx)
if query.ParentId != 0 {
res = res.Where("parent_entry_id = ?", query.ParentId)
}
@@ -128,7 +129,7 @@ func (p *PostgresClient) Search(ctx context.Context, query vector.VectorDocQuery
}
results := make([]*vector.Doc, 0)
for _, index := range minKIndexes {
- i := index.Object.(Index)
+ i := index.Object.(db.Index)
results = append(results, i.ToDoc())
}
@@ -136,8 +137,8 @@ func (p *PostgresClient) Search(ctx context.Context, query vector.VectorDocQuery
}
func (p *PostgresClient) Get(ctx context.Context, oid int64, name string, group int) (*vector.Element, error) {
- vModel := &Index{}
- tx := p.dEntity.WithNamespace(ctx).Where("name = ? AND idx_group = ?", name, group)
+ vModel := &db.Index{}
+ tx := p.DEntity.WithNamespace(ctx).Where("name = ? AND idx_group = ?", name, group)
if oid != 0 {
tx = tx.Where("oid = ?", oid)
}
@@ -155,7 +156,7 @@ var _ store.VectorStore = &PostgresClient{}
func (p *PostgresClient) Inited(ctx context.Context) (bool, error) {
var count int64
- res := p.dEntity.WithContext(ctx).Model(&BleveKV{}).Count(&count)
+ res := p.DEntity.WithContext(ctx).Model(&db.BleveKV{}).Count(&count)
if res.Error != nil {
return false, res.Error
}
From d0281370d4c3808c2c11cd7ef1bc1635179c79a4 Mon Sep 17 00:00:00 2001
From: zwwhdls
Date: Tue, 24 Dec 2024 21:12:12 +0800
Subject: [PATCH 3/3] update migrate
Signed-off-by: zwwhdls
---
pkg/store/db/migrate.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/pkg/store/db/migrate.go b/pkg/store/db/migrate.go
index 3bd1094..956f530 100644
--- a/pkg/store/db/migrate.go
+++ b/pkg/store/db/migrate.go
@@ -74,6 +74,7 @@ func buildMigrations() []*gormigrate.Migration {
if err != nil {
return err
}
+ _ = db.Exec("CREATE EXTENSION pg_trgm;")
_ = db.Exec("CREATE INDEX idx_document_token ON public.document USING gin (token);")
return nil
},