nodebb-plugin-dbsearch 6.2.9 → 6.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/dbsearch.js CHANGED
@@ -264,7 +264,7 @@ search.reindex = async function () {
264
264
 
265
265
  async function reIndexTopics() {
266
266
  await batch.processSortedSet('topics:tid', async (tids) => {
267
- const topicData = await topics.getTopicsFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted']);
267
+ const topicData = await topics.getTopicsFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted', 'timestamp']);
268
268
  await topicsSave(topicData);
269
269
  }, {
270
270
  batch: batchSize,
@@ -288,6 +288,9 @@ async function topicsSave(topics) {
288
288
  if (topicData.uid) {
289
289
  indexData.uid = topicData.uid;
290
290
  }
291
+ if (topicData.timestamp) {
292
+ indexData.timestamp = topicData.timestamp;
293
+ }
291
294
  if (!Object.keys(indexData).length) {
292
295
  return null;
293
296
  }
@@ -307,7 +310,7 @@ async function topicsSave(topics) {
307
310
 
308
311
  async function reIndexPosts() {
309
312
  await batch.processSortedSet('posts:pid', async (pids) => {
310
- let postData = await posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted']);
313
+ let postData = await posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted', 'timestamp']);
311
314
  postData = postData.filter(p => p && p.deleted !== 1);
312
315
  const tids = _.uniq(postData.map(p => p.tid));
313
316
  const topicData = await topics.getTopicsFields(tids, ['deleted', 'cid']);
@@ -341,6 +344,9 @@ async function postsSave(posts) {
341
344
  if (postData.uid) {
342
345
  indexData.uid = postData.uid;
343
346
  }
347
+ if (postData.timestamp) {
348
+ indexData.timestamp = postData.timestamp;
349
+ }
344
350
  if (!Object.keys(indexData).length) {
345
351
  return null;
346
352
  }
@@ -369,7 +375,7 @@ async function reIndexMessages() {
369
375
  }
370
376
 
371
377
  async function messagesSave(msgs) {
372
- msgs = msgs.filter(m => m && m.mid && parseInt(m.deleted, 10) !== 1 && parseInt(m.system, 10) !== 1);
378
+ msgs = msgs.filter(m => m && utils.isNumber(m.mid) && parseInt(m.deleted, 10) !== 1 && parseInt(m.system, 10) !== 1);
373
379
 
374
380
  let data = msgs.map((msgData) => {
375
381
  const indexData = {};
@@ -400,6 +406,7 @@ async function messagesSave(msgs) {
400
406
  }
401
407
 
402
408
  async function searchRemove(key, ids) {
409
+ ids = ids.filter(id => id && utils.isNumber(id));
403
410
  await db.searchRemove(key, ids);
404
411
  if (key === 'topic') {
405
412
  await db.incrObjectFieldBy('nodebb-plugin-dbsearch', 'topicsIndexed', -ids.length);
@@ -415,7 +422,7 @@ async function reIndexTids(tids) {
415
422
  return;
416
423
  }
417
424
 
418
- let topicData = await topics.getTopicsFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted', 'mainPid']);
425
+ let topicData = await topics.getTopicsFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted', 'mainPid', 'timestamp']);
419
426
  topicData = topicData.filter(t => t.tid && t.deleted !== 1);
420
427
  if (!topicData.length) {
421
428
  return;
@@ -448,7 +455,7 @@ async function reIndexPids(pids, topic) {
448
455
  if (parseInt(topic.deleted, 10) === 1) {
449
456
  return;
450
457
  }
451
- const postData = await posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted']);
458
+ const postData = await posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted', 'timestamp']);
452
459
  postData.forEach((post) => {
453
460
  if (post && topic) {
454
461
  post.cid = topic.cid;
package/lib/mongo.js CHANGED
@@ -12,7 +12,9 @@ exports.createIndices = async function (language) {
12
12
 
13
13
  if (nconf.get('isPrimary') && !nconf.get('jobsDisabled')) {
14
14
  await db.client.collection('searchtopic').createIndex({ content: 'text', uid: 1, cid: 1 }, options);
15
+ await db.client.collection('searchtopic').createIndex({ ts: 1 }, options);
15
16
  await db.client.collection('searchpost').createIndex({ content: 'text', uid: 1, cid: 1 }, options);
17
+ await db.client.collection('searchpost').createIndex({ ts: 1 }, options);
16
18
  await db.client.collection('searchchat').createIndex({ content: 'text', roomId: 1, uid: 1 }, options);
17
19
  }
18
20
  };
@@ -41,7 +43,11 @@ exports.searchIndex = async function (key, data, ids) {
41
43
  const setData = {};
42
44
  Object.keys(data[index]).forEach((field) => {
43
45
  if (data[index].hasOwnProperty(field) && data[index][field]) {
44
- setData[field] = data[index][field].toString();
46
+ if (field === 'timestamp') {
47
+ setData.ts = parseInt(data[index][field], 10);
48
+ } else {
49
+ setData[field] = data[index][field].toString();
50
+ }
45
51
  }
46
52
  });
47
53
 
@@ -73,15 +79,25 @@ exports.search = async function (key, data, limit) {
73
79
  }
74
80
  }
75
81
 
82
+ if (data.searchData.timeFilter && data.searchData.timeRange) {
83
+ const timeRange = parseInt(data.searchData.timeRange, 10) * 1000;
84
+ if (timeRange) {
85
+ const ts = Date.now() - timeRange;
86
+ searchQuery.ts = data.searchData.timeFilter === 'newer' ?
87
+ { $gte: ts } :
88
+ { $lte: ts };
89
+ }
90
+ }
91
+
76
92
  const aggregate = [{ $match: searchQuery }];
77
93
  if (searchQuery.$text) {
78
94
  const sortQuery = { score: { $meta: 'textScore' } };
79
95
  if (data.searchData.sortBy === 'timestamp' || data.searchData.sortBy === 'topic.timestamp') {
80
- sortQuery._id = data.searchData.sortDirection === 'asc' ? 1 : -1;
96
+ sortQuery.ts = data.searchData.sortDirection === 'asc' ? 1 : -1;
81
97
  }
82
98
  aggregate.push({ $sort: sortQuery });
83
99
  } else {
84
- aggregate.push({ $sort: { _id: data.searchData.sortDirection === 'asc' ? 1 : -1 } });
100
+ aggregate.push({ $sort: { ts: data.searchData.sortDirection === 'asc' ? 1 : -1 } });
85
101
  }
86
102
  aggregate.push({ $limit: parseInt(limit, 10) });
87
103
  aggregate.push({ $project: { _id: 1 } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-dbsearch",
3
- "version": "6.2.9",
3
+ "version": "6.2.11",
4
4
  "description": "A Plugin that lets users search posts and topics",
5
5
  "main": "index.js",
6
6
  "repository": {
package/plugin.json CHANGED
@@ -6,7 +6,8 @@
6
6
  "library": "./index.js",
7
7
  "upgrades": [
8
8
  "upgrades/dbsearch_change_mongodb_schema.js",
9
- "upgrades/dbsearch_change_integer_index.js"
9
+ "upgrades/dbsearch_change_integer_index.js",
10
+ "upgrades/dbsearch_mongodb_ts_index.js"
10
11
  ],
11
12
  "hooks": [
12
13
  { "hook": "static:app.load", "method": "init" },
@@ -33,13 +33,13 @@ module.exports = {
33
33
 
34
34
  if (mainDB === 'mongo') {
35
35
  const topics = await db.client.collection('searchtopic').find({}).toArray();
36
- const posts = await db.client.collection('searchposts').find({}).toArray();
36
+ const posts = await db.client.collection('searchpost').find({}).toArray();
37
37
  const chats = await db.client.collection('searchchat').find({}).toArray();
38
38
 
39
39
  progress.total = topics.length + posts.length + chats.length;
40
40
 
41
41
  await convertIdToString('searchtopic', topics);
42
- await convertIdToString('searchposts', posts);
42
+ await convertIdToString('searchpost', posts);
43
43
  await convertIdToString('searchchat', chats);
44
44
 
45
45
  return;
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+
4
+ const db = module.parent.require('./database');
5
+
6
+ module.exports = {
7
+ name: 'Add timestamp field to searchtopic searchpost collections',
8
+ timestamp: Date.UTC(2025, 1, 18),
9
+ method: async function () {
10
+ const { progress } = this;
11
+ const nconf = require.main.require('nconf');
12
+ const isMongo = nconf.get('database') === 'mongo';
13
+ if (!isMongo) {
14
+ return;
15
+ }
16
+
17
+ async function addTsField(collection, docs) {
18
+ for (const doc of docs) {
19
+ if (doc._id) {
20
+ const stringId = doc._id;
21
+ let ts = 0;
22
+ if (collection === 'searchtopic') {
23
+ // eslint-disable-next-line no-await-in-loop
24
+ ts = await db.getObjectField(`topic:${stringId}`, 'timestamp');
25
+ } else if (collection === 'searchpost') {
26
+ // eslint-disable-next-line no-await-in-loop
27
+ ts = await db.getObjectField(`post:${stringId}`, 'timestamp');
28
+ }
29
+ ts = parseInt(ts, 10);
30
+ if (ts) {
31
+ // eslint-disable-next-line no-await-in-loop
32
+ await db.client.collection(collection).updateOne({
33
+ _id: stringId,
34
+ }, { $set: { ts } });
35
+ }
36
+ }
37
+ progress.incr(1);
38
+ }
39
+ }
40
+ await db.client.collection('searchtopic').createIndex({ ts: 1 }, { });
41
+ await db.client.collection('searchpost').createIndex({ ts: 1 }, { });
42
+
43
+ const topics = await db.client.collection('searchtopic').find({}).toArray();
44
+ const posts = await db.client.collection('searchpost').find({}).toArray();
45
+
46
+ progress.total = topics.length + posts.length;
47
+
48
+ await addTsField('searchtopic', topics);
49
+ await addTsField('searchpost', posts);
50
+ },
51
+ };