1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-21 14:19:43 +02:00

Improved full text search matching

This commit is contained in:
sauls8t 2018-03-19 15:04:02 +00:00
parent eb3bebf20d
commit f825e9fdc9
9 changed files with 82 additions and 54 deletions

View file

@ -1,6 +1,6 @@
/* enterprise edition */ /* enterprise edition */
-- document lifecycle and versions -- document lifecycle and versioning
ALTER TABLE document ADD COLUMN `lifecycle` INT NOT NULL DEFAULT 1 AFTER `approval`; ALTER TABLE document ADD COLUMN `lifecycle` INT NOT NULL DEFAULT 1 AFTER `approval`;
ALTER TABLE document ADD COLUMN `versioned` INT NOT NULL DEFAULT 0 AFTER `lifecycle`; ALTER TABLE document ADD COLUMN `versioned` INT NOT NULL DEFAULT 0 AFTER `lifecycle`;
ALTER TABLE document ADD COLUMN `versionid` VARCHAR(100) DEFAULT '' NOT NULL AFTER `versioned`; ALTER TABLE document ADD COLUMN `versionid` VARCHAR(100) DEFAULT '' NOT NULL AFTER `versioned`;
@ -19,4 +19,9 @@ INSERT INTO permission(orgid, who, whoid, action, scope, location, refid, create
FROM permission FROM permission
WHERE action = 'doc-edit' OR action = 'doc-approve'; WHERE action = 'doc-edit' OR action = 'doc-approve';
-- implement document section name search indexing
INSERT INTO search (orgid, documentid, itemid, itemtype, content)
SELECT orgid, documentid, refid as itemid, "page" as itemtype, title as content
FROM page WHERE status=0
-- deprecations -- deprecations

View file

@ -269,6 +269,11 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
if d.Lifecycle == workflow.LifecycleLive { if d.Lifecycle == workflow.LifecycleLive {
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID) a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
go h.Indexer.IndexDocument(ctx, d, a) go h.Indexer.IndexDocument(ctx, d, a)
pages, _ := h.Store.Page.GetPages(ctx, d.RefID)
for i := range pages {
go h.Indexer.IndexContent(ctx, pages[i])
}
} else { } else {
go h.Indexer.DeleteDocument(ctx, d.RefID) go h.Indexer.DeleteDocument(ctx, d.RefID)
} }

View file

@ -121,6 +121,12 @@ func (s Scope) IndexContent(ctx domain.RequestContext, p page.Page) (err error)
err = errors.Wrap(err, "execute insert document content entry") err = errors.Wrap(err, "execute insert document content entry")
} }
_, err = ctx.Transaction.Exec("INSERT INTO search (orgid, documentid, itemid, itemtype, content) VALUES (?, ?, ?, ?, ?)",
ctx.OrgID, p.DocumentID, p.RefID, "page", p.Title)
if err != nil {
err = errors.Wrap(err, "execute insert document page title entry")
}
return nil return nil
} }
@ -148,7 +154,6 @@ func (s Scope) DeleteContent(ctx domain.RequestContext, pageID string) (err erro
// Visible documents include both those in the client's own organisation and those that are public, or whose visibility includes the client. // 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, q search.QueryOptions) (results []search.QueryResult, err error) { func (s Scope) Documents(ctx domain.RequestContext, q search.QueryOptions) (results []search.QueryResult, err error) {
q.Keywords = strings.TrimSpace(q.Keywords) q.Keywords = strings.TrimSpace(q.Keywords)
if len(q.Keywords) == 0 { if len(q.Keywords) == 0 {
return return
} }
@ -204,29 +209,29 @@ func (s Scope) Documents(ctx domain.RequestContext, q search.QueryOptions) (resu
func (s Scope) matchFullText(ctx domain.RequestContext, keywords, itemType string) (r []search.QueryResult, err error) { func (s Scope) matchFullText(ctx domain.RequestContext, keywords, itemType string) (r []search.QueryResult, err error) {
sql1 := ` sql1 := `
SELECT SELECT
s.id, s.orgid, s.documentid, s.itemid, s.itemtype, s.id, s.orgid, s.documentid, s.itemid, s.itemtype,
d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags, d.excerpt, d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags,
d.excerpt, d.template, d.versionid,
COALESCE(l.label,'Unknown') AS space COALESCE(l.label,'Unknown') AS space
FROM FROM
search s, search s,
document d document d
LEFT JOIN LEFT JOIN
label l ON l.orgid=d.orgid AND l.refid = d.labelid label l ON l.orgid=d.orgid AND l.refid = d.labelid
WHERE WHERE
s.orgid = ? s.orgid = ?
AND s.itemtype = ? AND s.itemtype = ?
AND s.documentid = d.refid AND s.documentid = d.refid
-- AND d.template = 0 AND d.labelid IN
AND d.labelid IN
( (
SELECT refid FROM label WHERE orgid=? SELECT refid FROM label WHERE orgid=? AND refid IN
AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN ( (
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view' SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view'
UNION ALL UNION ALL
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space' AND p.action='view' AND r.userid=? SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space' AND r.userid=?
)) )
) )
AND MATCH(s.content) AGAINST(? IN BOOLEAN MODE)` AND MATCH(s.content) AGAINST(? IN BOOLEAN MODE)`
err = s.Runtime.Db.Select(&r, err = s.Runtime.Db.Select(&r,
@ -235,7 +240,6 @@ func (s Scope) matchFullText(ctx domain.RequestContext, keywords, itemType strin
itemType, itemType,
ctx.OrgID, ctx.OrgID,
ctx.OrgID, ctx.OrgID,
ctx.OrgID,
ctx.UserID, ctx.UserID,
ctx.OrgID, ctx.OrgID,
ctx.UserID, ctx.UserID,
@ -245,7 +249,6 @@ func (s Scope) matchFullText(ctx domain.RequestContext, keywords, itemType strin
err = nil err = nil
r = []search.QueryResult{} r = []search.QueryResult{}
} }
if err != nil { if err != nil {
err = errors.Wrap(err, "search document "+itemType) err = errors.Wrap(err, "search document "+itemType)
} }
@ -261,25 +264,25 @@ func (s Scope) matchLike(ctx domain.RequestContext, keywords, itemType string) (
keywords = fmt.Sprintf("%%%s%%", keywords) keywords = fmt.Sprintf("%%%s%%", keywords)
sql1 := ` sql1 := `
SELECT SELECT
s.id, s.orgid, s.documentid, s.itemid, s.itemtype, s.id, s.orgid, s.documentid, s.itemid, s.itemtype,
d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags, d.excerpt, d.labelid as spaceid, COALESCE(d.title,'Unknown') AS document, d.tags, d.excerpt,
COALESCE(l.label,'Unknown') AS space COALESCE(l.label,'Unknown') AS space
FROM FROM
search s, search s,
document d document d
LEFT JOIN LEFT JOIN
label l ON l.orgid=d.orgid AND l.refid = d.labelid label l ON l.orgid=d.orgid AND l.refid = d.labelid
WHERE WHERE
s.orgid = ? s.orgid = ?
AND s.itemtype = ? AND s.itemtype = ?
AND s.documentid = d.refid AND s.documentid = d.refid
-- AND d.template = 0 -- AND d.template = 0
AND d.labelid IN AND d.labelid IN
( (
SELECT refid FROM label WHERE orgid=? SELECT refid FROM label WHERE orgid=?
AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN ( AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN (
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view' SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view'
UNION ALL UNION ALL
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role'
AND p.location='space' AND p.action='view' AND (r.userid=? OR r.userid='0') AND p.location='space' AND p.action='view' AND (r.userid=? OR r.userid='0')

View file

@ -12,21 +12,18 @@
import Component from '@ember/component'; import Component from '@ember/component';
export default Component.extend({ export default Component.extend({
resultPhrase: "", resultPhrase: '',
init() {
this._super(...arguments);
this.results = [];
},
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments);
let docs = this.get('results'); let docs = this.get('results');
let duped = []; let duped = [];
let phrase = 'Nothing found'; let phrase = 'Nothing found';
if (docs.length > 0) { if (docs.length > 0) {
duped = _.uniq(docs, function (item) { duped = _.uniq(docs, function (item) {
return item.documentId; return item.get('documentId');
}); });
let references = docs.length === 1 ? "reference" : "references"; let references = docs.length === 1 ? "reference" : "references";

View file

@ -24,5 +24,7 @@ export default Model.extend({
space: attr(), space: attr(),
spaceId: attr(), spaceId: attr(),
spaceSlug: attr(), spaceSlug: attr(),
template: attr(),
versionId: attr(),
selected: attr() selected: attr()
}); });

View file

@ -39,4 +39,4 @@ export default Service.extend({
return error; return error;
}); });
}, },
}); });

View file

@ -17,7 +17,6 @@
position: relative; position: relative;
margin: 0 0 30px 0; margin: 0 0 30px 0;
width: 100%; width: 100%;
// height: 150px;
&:hover { &:hover {
> .checkbox { > .checkbox {
@ -33,26 +32,33 @@
> .title { > .title {
color: $color-black; color: $color-black;
font-size: 1.3rem; font-weight: bold;
font-size: 1.4rem;
margin-bottom: 5px;
> .version {
font-size: 1.1rem;
font-weight: bold;
color: $color-gray;
}
}
> .space {
color: $color-off-black;
font-size: 1.2rem;
margin-bottom: 5px; margin-bottom: 5px;
} }
> .snippet { > .snippet {
color: $color-gray; color: $color-gray;
font-size: 1rem; font-size: 1.1rem;
line-height: 24px; margin-bottom: 10px;
} }
&:hover { &:hover {
color: $color-gray;
> .title { > .title {
color: $color-link; color: $color-link;
} }
> .snippet {
color: $color-link;
}
} }
} }
@ -61,7 +67,7 @@
display: inline-block; display: inline-block;
margin: 5px 10px 0 5px; margin: 5px 10px 0 5px;
color: $color-gray; color: $color-gray;
font-size: 0.875rem; font-size: 1rem;
font-style: italic; font-style: italic;
&:hover { &:hover {

View file

@ -1,15 +1,23 @@
<div class="view-search my-5"> <div class="view-search my-5">
<div class="heading">{{resultPhrase}}</div> <div class="heading">{{resultPhrase}}</div>
<ul class="documents"> <ul class="documents">
{{#each documents key="id" as |result index|}} {{#each documents key="id" as |result index|}}
<li class="document"> <li class="document">
<a class="link" href="s/{{result.spaceId}}/{{result.spaceSlug}}/d/{{ result.documentId }}/{{result.documentSlug}}?page={{ result.itemId }}"> <a class="link" href="s/{{result.spaceId}}/{{result.spaceSlug}}/d/{{ result.documentId }}/{{result.documentSlug}}?page={{ result.itemId }}">
<div class="title">{{result.document}}</div> <div class="title">
{{result.document}}
{{#if (gt result.versionId.length 0)}}
<span class="version">&nbsp;&nbsp;{{result.versionId}}</span>
{{/if}}
</div>
<div class="space">{{result.space}}</div>
<div class="snippet">{{result.excerpt}}</div> <div class="snippet">{{result.excerpt}}</div>
<div class="snippet">({{result.space}})</div>
{{folder/document-tags documentTags=result.tags}} {{folder/document-tags documentTags=result.tags}}
</a> {{#if result.template}}
</li> <button type="button" class="mt-3 btn btn-warning text-uppercase font-weight-bold">TEMPLATE</button>
{{/each}} {{/if}}
</ul> </a>
</div> </li>
{{/each}}
</ul>
</div>

View file

@ -34,4 +34,6 @@ type QueryResult struct {
SpaceID string `json:"spaceId"` SpaceID string `json:"spaceId"`
Space string `json:"space"` Space string `json:"space"`
SpaceSlug string `json:"spaceSlug"` SpaceSlug string `json:"spaceSlug"`
Template bool `json:"template"`
VersionID string `json:"versionId"`
} }