feat: Record search queries (#1554)

* Record search queries

* feat: add totalCount to the search response

* feat: add comments to explain why we use setTimeout
This commit is contained in:
Renan Filipe
2020-09-22 03:05:42 -03:00
committed by GitHub
parent 0fa8a6ed2e
commit 98626ebbaf
9 changed files with 330 additions and 54 deletions

View File

@@ -11,6 +11,7 @@ import {
Document,
Event,
Revision,
SearchQuery,
Share,
Star,
User,
@@ -586,7 +587,7 @@ router.post("documents.search", auth(), pagination(), async (ctx) => {
);
}
const results = await Document.searchForUser(user, query, {
const { results, totalCount } = await Document.searchForUser(user, query, {
includeArchived: includeArchived === "true",
includeDrafts: includeDrafts === "true",
collaboratorIds,
@@ -604,6 +605,14 @@ router.post("documents.search", auth(), pagination(), async (ctx) => {
})
);
SearchQuery.create({
userId: user.id,
teamId: user.teamId,
source: "app",
query,
results: totalCount,
});
const policies = presentPolicies(user, documents);
ctx.body = {

View File

@@ -8,6 +8,7 @@ import {
Revision,
Backlink,
CollectionUser,
SearchQuery,
} from "../models";
import {
buildShare,
@@ -954,6 +955,25 @@ describe("#documents.search", () => {
expect(res.status).toEqual(401);
expect(body).toMatchSnapshot();
});
it("should save search term, hits and source", async (done) => {
const { user } = await seed();
await server.post("/api/documents.search", {
body: { token: user.getJwtToken(), query: "my term" },
});
// setTimeout is needed here because SearchQuery is saved asynchronously
// in order to not slow down the response time.
setTimeout(async () => {
const searchQuery = await SearchQuery.findAll({
where: { query: "my term" },
});
expect(searchQuery.length).toBe(1);
expect(searchQuery[0].results).toBe(0);
expect(searchQuery[0].source).toBe("app");
done();
}, 100);
});
});
describe("#documents.archived", () => {

View File

@@ -2,7 +2,14 @@
import Router from "koa-router";
import { escapeRegExp } from "lodash";
import { AuthenticationError, InvalidRequestError } from "../errors";
import { Authentication, Document, User, Team, Collection } from "../models";
import {
Authentication,
Document,
User,
Team,
Collection,
SearchQuery,
} from "../models";
import { presentSlackAttachment } from "../presenters";
import * as Slack from "../slack";
const router = new Router();
@@ -146,10 +153,18 @@ router.post("hooks.slack", async (ctx) => {
const options = {
limit: 5,
};
const results = user
const { results, totalCount } = user
? await Document.searchForUser(user, text, options)
: await Document.searchForTeam(team, text, options);
SearchQuery.create({
userId: user ? user.id : null,
teamId: team.id,
source: "slack",
query: text,
results: totalCount,
});
if (results.length) {
const attachments = [];
for (const result of results) {

View File

@@ -1,7 +1,7 @@
/* eslint-disable flowtype/require-valid-file-annotation */
import TestServer from "fetch-test-server";
import app from "../app";
import { Authentication } from "../models";
import { Authentication, SearchQuery } from "../models";
import * as Slack from "../slack";
import { buildDocument } from "../test/factories";
import { flushdb, seed } from "../test/support";
@@ -132,6 +132,30 @@ describe("#hooks.slack", () => {
);
});
it("should save search term, hits and source", async (done) => {
const { user, team } = await seed();
await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
text: "contains",
},
});
// setTimeout is needed here because SearchQuery is saved asynchronously
// in order to not slow down the response time.
setTimeout(async () => {
const searchQuery = await SearchQuery.findAll({
where: { query: "contains" },
});
expect(searchQuery.length).toBe(1);
expect(searchQuery[0].results).toBe(0);
expect(searchQuery[0].source).toBe("slack");
done();
}, 100);
});
it("should respond with help content for help keyword", async () => {
const { user, team } = await seed();
const res = await server.post("/api/hooks.slack", {