From 40f5e67ff0f803fab117c405a0614df915381433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=93=E3=81=B4=E3=81=AA=E3=81=9F=E3=81=BF=E3=81=BD?= Date: Thu, 21 Dec 2017 07:35:16 +0900 Subject: [PATCH] :v: --- src/api/endpoints/posts/search.ts | 130 ++++++++++++++---- .../app/common/scripts/parse-search-query.ts | 7 +- src/web/docs/search.ja.pug | 29 +++- 3 files changed, 131 insertions(+), 35 deletions(-) diff --git a/src/api/endpoints/posts/search.ts b/src/api/endpoints/posts/search.ts index 88cdd32dac..21e9134d38 100644 --- a/src/api/endpoints/posts/search.ts +++ b/src/api/endpoints/posts/search.ts @@ -34,13 +34,17 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const [following = null, followingErr] = $(params.following).optional.nullable.boolean().$; if (followingErr) return rej('invalid following param'); - // Get 'include_replies' parameter - const [includeReplies = true, includeRepliesErr] = $(params.include_replies).optional.boolean().$; - if (includeRepliesErr) return rej('invalid include_replies param'); + // Get 'reply' parameter + const [reply = null, replyErr] = $(params.reply).optional.nullable.boolean().$; + if (replyErr) return rej('invalid reply param'); - // Get 'with_media' parameter - const [withMedia = false, withMediaErr] = $(params.with_media).optional.boolean().$; - if (withMediaErr) return rej('invalid with_media param'); + // Get 'repost' parameter + const [repost = null, repostErr] = $(params.repost).optional.nullable.boolean().$; + if (repostErr) return rej('invalid repost param'); + + // Get 'media' parameter + const [media = null, mediaErr] = $(params.media).optional.nullable.boolean().$; + if (mediaErr) return rej('invalid media param'); // Get 'since_date' parameter const [sinceDate, sinceDateErr] = $(params.since_date).optional.number().$; @@ -72,53 +76,119 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // If Elasticsearch is available, search by it // If not, search by MongoDB (config.elasticsearch.enable ? byElasticsearch : byNative) - (res, rej, me, text, user, following, includeReplies, withMedia, sinceDate, untilDate, offset, limit); + (res, rej, me, text, user, following, reply, repost, media, sinceDate, untilDate, offset, limit); }); // Search by MongoDB -async function byNative(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { - const q: any = {}; +async function byNative(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { + const q: any = { + $and: [] + }; + + const push = q.$and.push; if (text) { - q.$and = text.split(' ').map(x => ({ - text: new RegExp(escapeRegexp(x)) - })); + push({ + $and: text.split(' ').map(x => ({ + text: new RegExp(escapeRegexp(x)) + })) + }); } if (userId) { - q.user_id = userId; + push({ + user_id: userId + }); } if (following != null) { const ids = await getFriends(me._id, false); - q.user_id = {}; - if (following) { - q.user_id.$in = ids; + push({ + user_id: following ? { + $in: ids + } : { + $nin: ids + } + }); + } + + if (reply != null) { + if (reply) { + push({ + reply_id: { + $exists: true, + $ne: null + } + }); } else { - q.user_id.$nin = ids; + push({ + $or: [{ + reply_id: { + $exists: false + } + }, { + reply_id: null + }] + }); } } - if (!includeReplies) { - q.reply_id = null; + if (repost != null) { + if (repost) { + push({ + repost_id: { + $exists: true, + $ne: null + } + }); + } else { + push({ + $or: [{ + repost_id: { + $exists: false + } + }, { + repost_id: null + }] + }); + } } - if (withMedia) { - q.media_ids = { - $exists: true, - $ne: null - }; + if (media != null) { + if (media) { + push({ + media_ids: { + $exists: true, + $ne: null + } + }); + } else { + push({ + $or: [{ + media_ids: { + $exists: false + } + }, { + media_ids: null + }] + }); + } } if (sinceDate) { - q.created_at = { - $gt: new Date(sinceDate) - }; + push({ + created_at: { + $gt: new Date(sinceDate) + } + }); } if (untilDate) { - if (q.created_at == undefined) q.created_at = {}; - q.created_at.$lt = new Date(untilDate); + push({ + created_at: { + $lt: new Date(untilDate) + } + }); } // Search posts @@ -137,7 +207,7 @@ async function byNative(res, rej, me, text, userId, following, includeReplies, w } // Search by Elasticsearch -async function byElasticsearch(res, rej, me, text, userId, following, includeReplies, withMedia, sinceDate, untilDate, offset, max) { +async function byElasticsearch(res, rej, me, text, userId, following, reply, repost, media, sinceDate, untilDate, offset, max) { const es = require('../../db/elasticsearch'); es.search({ diff --git a/src/web/app/common/scripts/parse-search-query.ts b/src/web/app/common/scripts/parse-search-query.ts index 62b2cf51b1..f65e4683a6 100644 --- a/src/web/app/common/scripts/parse-search-query.ts +++ b/src/web/app/common/scripts/parse-search-query.ts @@ -14,10 +14,13 @@ export default function(qs: string) { q['following'] = value == 'null' ? null : value == 'true'; break; case 'reply': - q['include_replies'] = value == 'true'; + q['reply'] = value == 'null' ? null : value == 'true'; + break; + case 'repost': + q['repost'] = value == 'null' ? null : value == 'true'; break; case 'media': - q['with_media'] = value == 'true'; + q['media'] = value == 'null' ? null : value == 'true'; break; case 'until': case 'since': diff --git a/src/web/docs/search.ja.pug b/src/web/docs/search.ja.pug index 7d4d23fb6a..d46e5f4a04 100644 --- a/src/web/docs/search.ja.pug +++ b/src/web/docs/search.ja.pug @@ -23,13 +23,36 @@ section td ユーザー名。投稿者を限定します。 tr td follow - td フォローしているユーザーのみに限定。(trueかfalse) + td + | true ... フォローしているユーザーに限定。 + br + | false ... フォローしていないユーザーに限定。 + br + | null ... 特に限定しない(デフォルト) tr td reply - td 返信を含めるか否か。(trueかfalse) + td + | true ... 返信に限定。 + br + | false ... 返信でない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) + tr + td repost + td + | true ... Repostに限定。 + br + | false ... Repostでない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) tr td media - td メディアが添付されているか。(trueかfalse) + td + | true ... メディアが添付されている投稿に限定。 + br + | false ... メディアが添付されていない投稿に限定。 + br + | null ... 特に限定しない(デフォルト) tr td until td 上限の日時。(YYYY-MM-DD)