1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-08-02 03:55:24 +02:00

new search options and schema

This commit is contained in:
Harvey Kandola 2017-08-15 14:15:31 +01:00
parent 6c3042fd4e
commit 2c5f73a486
14 changed files with 283 additions and 118 deletions

View file

@ -12,8 +12,8 @@
package mysql
import (
"database/sql"
"fmt"
"regexp"
"strings"
"time"
@ -244,68 +244,156 @@ func (s Scope) Delete(ctx domain.RequestContext, page page.Page) (err error) {
// Documents searches the documents that the client is allowed to see, using the keywords search string, then audits that search.
// Visible documents include both those in the client's own organisation and those that are public, or whose visibility includes the client.
func (s Scope) Documents(ctx domain.RequestContext, keywords string) (results []search.DocumentSearch, err error) {
if len(keywords) == 0 {
func (s Scope) Documents(ctx domain.RequestContext, q search.QueryOptions) (results []search.QueryResult, err error) {
q.Keywords = strings.TrimSpace(q.Keywords)
if len(q.Keywords) == 0 {
return
}
var tagQuery, keywordQuery string
results = []search.QueryResult{}
r, _ := regexp.Compile(`(#[a-z0-9][a-z0-9\-_]*)`)
res := r.FindAllString(keywords, -1)
if len(res) == 0 {
tagQuery = " "
} else {
if len(res) == 1 {
tagQuery = " AND document.tags LIKE '%" + res[0] + "#%' "
} else {
fmt.Println("lots of tags!")
tagQuery = " AND ("
for i := 0; i < len(res); i++ {
tagQuery += "document.tags LIKE '%" + res[i] + "#%'"
if i < len(res)-1 {
tagQuery += " OR "
}
}
tagQuery += ") "
// Match doc names
if q.Doc {
r1, err1 := s.matchFullText(ctx, q.Keywords, "doc")
if err1 != nil {
err = errors.Wrap(err1, "search document names")
return
}
keywords = r.ReplaceAllString(keywords, "")
keywords = strings.Replace(keywords, " ", "", -1)
results = append(results, r1...)
}
keywords = strings.TrimSpace(keywords)
// Match doc content
if q.Content {
r2, err2 := s.matchFullText(ctx, q.Keywords, "page")
if err2 != nil {
err = errors.Wrap(err2, "search document content")
return
}
if len(keywords) > 0 {
keywordQuery = "AND MATCH(documenttitle,pagetitle,body) AGAINST('" + keywords + "' in boolean mode)"
results = append(results, r2...)
}
sql := `SELECT search.id, documentid, pagetitle, document.labelid, document.title as documenttitle, document.tags,
COALESCE(label.label,'Unknown') AS labelname, document.excerpt as documentexcerpt
FROM search, document LEFT JOIN label ON label.orgid=document.orgid AND label.refid = document.labelid
WHERE search.documentid = document.refid AND search.orgid=? AND document.template=0 ` + tagQuery +
`AND document.labelid IN
(SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1))) ` + keywordQuery
// Match doc tags
if q.Tag {
r3, err3 := s.matchFullText(ctx, q.Keywords, "tag")
if err3 != nil {
err = errors.Wrap(err3, "search document tag")
return
}
err = s.Runtime.Db.Select(&results,
sql,
results = append(results, r3...)
}
// Match doc attachments
if q.Attachment {
r4, err4 := s.matchLike(ctx, q.Keywords, "file")
if err4 != nil {
err = errors.Wrap(err4, "search document attachments")
return
}
results = append(results, r4...)
}
return
}
func (s Scope) matchFullText(ctx domain.RequestContext, keywords, itemType string) (r []search.QueryResult, err error) {
sql1 := `
SELECT
s.id, s.orgid, s.documentid, s.itemid, s.itemtype,
d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags, d.excerpt,
COALESCE(l.label,'Unknown') AS space
FROM
search s,
document d
LEFT JOIN
label l ON l.orgid=d.orgid AND l.refid = d.labelid
WHERE
s.orgid = ?
AND s.itemtype = ?
AND s.documentid = d.refid
-- AND d.template = 0
AND d.labelid IN (SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
AND MATCH(s.content) AGAINST(? IN BOOLEAN MODE)`
err = s.Runtime.Db.Select(&r,
sql1,
ctx.OrgID,
itemType,
ctx.OrgID,
ctx.UserID,
ctx.OrgID,
ctx.OrgID,
ctx.OrgID,
ctx.OrgID,
ctx.UserID)
ctx.UserID,
keywords)
if err == sql.ErrNoRows {
err = nil
r = []search.QueryResult{}
}
if err != nil {
err = errors.Wrap(err, "search documents")
err = errors.Wrap(err, "search document "+itemType)
return
}
return
}
func (s Scope) matchLike(ctx domain.RequestContext, keywords, itemType string) (r []search.QueryResult, err error) {
// LIKE clause does not like quotes!
keywords = strings.Replace(keywords, "'", "", -1)
keywords = strings.Replace(keywords, "\"", "", -1)
keywords = strings.Replace(keywords, "%", "", -1)
keywords = fmt.Sprintf("%%%s%%", keywords)
sql1 := `
SELECT
s.id, s.orgid, s.documentid, s.itemid, s.itemtype,
d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags, d.excerpt,
COALESCE(l.label,'Unknown') AS space
FROM
search s,
document d
LEFT JOIN
label l ON l.orgid=d.orgid AND l.refid = d.labelid
WHERE
s.orgid = ?
AND s.itemtype = ?
AND s.documentid = d.refid
-- AND d.template = 0
AND d.labelid IN (SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
AND s.content LIKE ?`
err = s.Runtime.Db.Select(&r,
sql1,
ctx.OrgID,
itemType,
ctx.OrgID,
ctx.UserID,
ctx.OrgID,
ctx.OrgID,
ctx.OrgID,
ctx.OrgID,
ctx.UserID,
keywords)
if err == sql.ErrNoRows {
err = nil
r = []search.QueryResult{}
}
if err != nil {
err = errors.Wrap(err, "search document "+itemType)
return
}