search sort, search in posts, titles, posts& titles

v1.18.x
barisusakli 10 years ago
parent 957415463f
commit eff1256dfb

@ -3,6 +3,8 @@
"no-matches": "No matches found",
"in": "In",
"by": "By",
"titles": "Titles",
"titles-posts": "Titles and Posts",
"posted-by": "Posted by",
"in-categories": "In Categories",
"search-child-categories": "Search child categories",
@ -19,5 +21,16 @@
"one-month": "One month",
"three-months": "Three months",
"six-months": "Six months",
"one-year": "One year"
"one-year": "One year",
"sort-by": "Sort by",
"post-time": "Post time",
"last-reply-time": "Last reply time",
"topic-title": "Topic title",
"number-of-replies": "Number of replies",
"number-of-views": "Number of views",
"topic-start-date": "Topic start date",
"username": "Username",
"category": "Category",
"descending": "In descending order",
"ascending": "In ascending order"
}

@ -436,7 +436,7 @@ app.uid = null;
e.preventDefault();
var input = $(this).find('input');
search.query({term: input.val(), in: 'posts'}, function() {
search.query({term: input.val()}, function() {
input.val('');
});
});

@ -15,26 +15,31 @@ define('forum/search', ['search'], function(searchModule) {
fillOutFormFromQueryParams();
searchIn.on('change', function() {
$('.post-search-item').toggleClass('hide', searchIn.val() !== 'posts');
updateFormItemVisiblity(searchIn.val());
});
highlightMatches(searchQuery);
$('#advanced-search').off('submit').on('submit', function(e) {
e.preventDefault();
var input = $(this).find('#search-input');
var $this = $(this)
var input = $this.find('#search-input');
searchModule.query({
var searchData = {
term: input.val(),
in: $(this).find('#search-in').val(),
by: $(this).find('#posted-by-user').val(),
categories: $(this).find('#posted-in-categories').val(),
searchChildren: $(this).find('#search-children').is(':checked'),
replies: $(this).find('#reply-count').val(),
repliesFilter: $(this).find('#reply-count-filter').val(),
timeFilter: $(this).find('#post-time-filter').val(),
timeRange: $(this).find('#post-time-range').val()
}, function() {
in: $this.find('#search-in').val(),
by: $this.find('#posted-by-user').val(),
categories: $this.find('#posted-in-categories').val(),
searchChildren: $this.find('#search-children').is(':checked'),
replies: $this.find('#reply-count').val(),
repliesFilter: $this.find('#reply-count-filter').val(),
timeFilter: $this.find('#post-time-filter').val(),
timeRange: $this.find('#post-time-range').val(),
sortBy: $this.find('#post-sort-by').val(),
sortDirection: $this.find('#post-sort-direction').val()
};
searchModule.query(searchData, function() {
input.val('');
});
});
@ -42,12 +47,17 @@ define('forum/search', ['search'], function(searchModule) {
enableAutoComplete();
};
function updateFormItemVisiblity(searchIn) {
var hide = searchIn.indexOf('posts') === -1 && searchIn.indexOf('titles') === -1;
$('.post-search-item').toggleClass('hide', hide);
}
function fillOutFormFromQueryParams() {
var params = utils.params();
if (params) {
if (params.in) {
$('#search-in').val(params.in);
$('.post-search-item').toggleClass('hide', params.in !== 'posts');
updateFormItemVisiblity(params.in);
}
if (params.by) {
@ -71,6 +81,11 @@ define('forum/search', ['search'], function(searchModule) {
$('#post-time-range').val(params.timeRange);
$('#post-time-filter').val(params.timeFilter);
}
if (params.sortBy) {
$('#post-sort-by').val(params.sortBy);
$('#post-sort-direction').val(params.sortDirection);
}
}
}

@ -9,8 +9,6 @@ define('search', ['navigator'], function(nav) {
Search.query = function(data, callback) {
var term = data.term;
var searchIn = data.in || 'posts';
var postedBy = data.by || '';
// Detect if a tid was specified
var topicSearch = term.match(/in:topic-([\d]+)/);
@ -23,29 +21,8 @@ define('search', ['navigator'], function(nav) {
} catch(e) {
return app.alertError('[[error:invalid-search-term]]');
}
var query = {in: searchIn};
if (postedBy && searchIn === 'posts') {
query.by = postedBy;
}
if (data.categories && data.categories.length) {
query.categories = data.categories;
if (data.searchChildren) {
query.searchChildren = data.searchChildren;
}
}
if (parseInt(data.replies, 10) > 0) {
query.replies = data.replies;
query.repliesFilter = data.repliesFilter || 'atleast';
}
if (data.timeRange) {
query.timeRange = data.timeRange;
query.timeFilter = data.timeFilter || 'newer';
}
ajaxify.go('search/' + term + '?' + decodeURIComponent($.param(query)));
ajaxify.go('search/' + term + '?' + createQueryString(data));
callback();
} else {
var cleanedTerm = term.replace(topicSearch[0], ''),
@ -55,6 +32,39 @@ define('search', ['navigator'], function(nav) {
}
};
function createQueryString(data) {
var searchIn = data.in || 'titlesposts';
var postedBy = data.by || '';
var query = {in: searchIn};
if (postedBy && (searchIn === 'posts' || searchIn === 'titles' || searchIn === 'titlesposts')) {
query.by = postedBy;
}
if (data.categories && data.categories.length) {
query.categories = data.categories;
if (data.searchChildren) {
query.searchChildren = data.searchChildren;
}
}
if (parseInt(data.replies, 10) > 0) {
query.replies = data.replies;
query.repliesFilter = data.repliesFilter || 'atleast';
}
if (data.timeRange) {
query.timeRange = data.timeRange;
query.timeFilter = data.timeFilter || 'newer';
}
if (data.sortBy) {
query.sortBy = data.sortBy;
query.sortDirection = data.sortDirection;
}
return decodeURIComponent($.param(query));
}
Search.queryTopic = function(tid, term, callback) {
socket.emit('topics.search', {
tid: tid,

@ -28,7 +28,6 @@ searchController.search = function(req, res, next) {
time: 0,
search_query: '',
posts: [],
topics: [],
users: [],
tags: [],
categories: categories,
@ -49,6 +48,8 @@ searchController.search = function(req, res, next) {
repliesFilter: req.query.repliesFilter,
timeRange: req.query.timeRange,
timeFilter: req.query.timeFilter,
sortBy: req.query.sortBy,
sortDirection: req.query.sortDirection,
page: page,
uid: uid
}, function(err, results) {

@ -8,7 +8,8 @@ var async = require('async'),
categories = require('./categories'),
user = require('./user'),
plugins = require('./plugins'),
privileges = require('./privileges');
privileges = require('./privileges'),
utils = require('../public/src/utils');
var search = {};
@ -21,6 +22,9 @@ search.search = function(data, callback) {
}
result.search_query = query;
if (searchIn === 'titles' || searchIn === 'titlesposts') {
searchIn = 'posts';
}
result[searchIn] = data.matches;
result.matchCount = data.matchCount;
result.hidePostedBy = searchIn !== 'posts';
@ -31,7 +35,7 @@ search.search = function(data, callback) {
var start = process.hrtime();
var query = data.query;
var searchIn = data.searchIn || 'posts';
var searchIn = data.searchIn || 'titlesposts';
var result = {
posts: [],
@ -39,8 +43,8 @@ search.search = function(data, callback) {
tags: []
};
if (searchIn === 'posts') {
searchInPosts(query, data, done);
if (searchIn === 'posts' || searchIn === 'titles' || searchIn === 'titlesposts') {
searchInContent(query, data, done);
} else if (searchIn === 'users') {
searchInUsers(query, data.uid, done);
} else if (searchIn === 'tags') {
@ -50,14 +54,22 @@ search.search = function(data, callback) {
}
};
function searchInPosts(query, data, callback) {
function searchInContent(query, data, callback) {
data.uid = data.uid || 0;
async.parallel({
pids: function(next) {
searchQuery('post', query, next);
if (data.searchIn === 'posts' || data.searchIn === 'titlesposts') {
searchQuery('post', query, next);
} else {
next(null, []);
}
},
tids: function(next) {
searchQuery('topic', query, next);
if (data.searchIn === 'titles' || data.searchIn === 'titlesposts') {
searchQuery('topic', query, next);
} else {
next(null, []);
}
},
searchCategories: function(next) {
getSearchCategories(data, next);
@ -104,24 +116,9 @@ function searchInPosts(query, data, callback) {
}
function filterAndSort(pids, data, searchCategories, callback) {
var postFields = ['pid', 'tid', 'timestamp'];
var topicFields = [];
if (data.postedBy) {
postFields.push('uid');
}
if (searchCategories.length) {
topicFields.push('cid');
}
if (data.replies) {
topicFields.push('postcount');
}
async.parallel({
posts: function(next) {
getMatchedPosts(pids, postFields, topicFields, next);
getMatchedPosts(pids, data, searchCategories, next);
},
postedByUid: function(next) {
if (data.postedBy) {
@ -154,28 +151,130 @@ function filterAndSort(pids, data, searchCategories, callback) {
});
}
function getMatchedPosts(pids, postFields, topicFields, callback) {
var keys = pids.map(function(pid) {
return 'post:' + pid;
});
function getMatchedPosts(pids, data, searchCategories, callback) {
var postFields = ['pid', 'tid', 'timestamp'];
var topicFields = [];
var categoryFields = [];
if (data.postedBy) {
postFields.push('uid');
}
if (searchCategories.length || (data.sortBy && data.sortBy.startsWith('category.'))) {
topicFields.push('cid');
}
if (data.replies) {
topicFields.push('postcount');
}
if (data.sortBy) {
if (data.sortBy.startsWith('topic.')) {
topicFields.push(data.sortBy.split('.')[1]);
} else if (data.sortBy.startsWith('user.')) {
postFields.push('uid');
} else if (data.sortBy.startsWith('category.')) {
categoryFields.push(data.sortBy.split('.')[1]);
} else if (data.sortBy.startsWith('teaser')) {
topicFields.push('teaserPid');
}
}
var posts;
async.waterfall([
function(next) {
var keys = pids.map(function(pid) {
return 'post:' + pid;
});
db.getObjectsFields(keys, postFields, next);
},
function(_posts, next) {
posts = _posts;
if (!topicFields.length) {
return callback(null, posts);
}
var topicKeys = posts.map(function(post) {
return 'topic:' + post.tid;
});
db.getObjectsFields(topicKeys, topicFields, next);
async.parallel({
users: function(next) {
if (data.sortBy && data.sortBy.startsWith('user')) {
var uids = posts.map(function(post) {
return post.uid;
});
user.getMultipleUserFields(uids, ['username'], next);
} else {
next();
}
},
topics: function(next) {
if (!topicFields.length) {
return next();
}
var topics;
async.waterfall([
function(next) {
var topicKeys = posts.map(function(post) {
return 'topic:' + post.tid;
});
db.getObjectsFields(topicKeys, topicFields, next);
},
function(_topics, next) {
topics = _topics;
async.parallel({
teasers: function(next) {
if (topicFields.indexOf('teaserPid') !== -1) {
var teaserKeys = topics.map(function(topic) {
return 'post:' + topic.teaserPid;
});
db.getObjectsFields(teaserKeys, ['timestamp'], next);
} else {
next();
}
},
categories: function(next) {
if (!categoryFields.length) {
return next();
}
var cids = topics.map(function(topic) {
return 'category:' + topic.cid;
});
db.getObjectsFields(cids, categoryFields, next);
}
}, next);
}
], function(err, results) {
if (err) {
return next(err);
}
topics.forEach(function(topic, index) {
if (topic && results.categories && results.categories[index]) {
topic.category = results.categories[index];
}
if (topic && results.teasers && results.teasers[index]) {
topic.teaser = results.teasers[index];
}
});
next(null, topics);
});
}
}, next);
},
function(topics, next) {
function(results, next) {
posts.forEach(function(post, index) {
post.topic = topics[index];
if (results.topics && results.topics[index]) {
post.topic = results.topics[index];
if (results.topics[index].category) {
post.category = results.topics[index].category;
}
if (results.topics[index].teaser) {
post.teaser = results.topics[index].teaser;
}
}
if (results.users && results.users[index]) {
post.user = results.users[index];
}
});
next(null, posts);
@ -236,8 +335,75 @@ function filterByTimerange(posts, timeRange, timeFilter) {
}
function sortPosts(posts, data) {
if (!posts.length) {
return;
}
data.sortBy = data.sortBy || 'timestamp';
data.sortDirection = data.sortDirection || 'desc';
if (data.sortBy === 'timestamp') {
if (data.sortDirection === 'desc') {
posts.sort(function(p1, p2) {
return p2.timestamp - p1.timestamp;
});
} else {
posts.sort(function(p1, p2) {
return p1.timestamp - p2.timestamp;
});
}
return;
}
var firstPost = posts[0];
var fields = data.sortBy.split('.');
if (!fields || fields.length !== 2 || !firstPost[fields[0]] || !firstPost[fields[0]][fields[1]]) {
return;
}
var value = firstPost[fields[0]][fields[1]];
var isNumeric = utils.isNumber(value);
if (isNumeric) {
if (data.sortDirection === 'desc') {
sortDescendingNumeric(posts, fields);
} else {
sortAscendingNumeric(posts, fields);
}
} else {
if (data.sortDirection === 'desc') {
sortDescendingAlpha(posts, fields);
} else {
sortAscendingAlpha(posts, fields);
}
}
}
function sortAscendingNumeric(posts, fields) {
posts.sort(function(p1, p2) {
return p1[fields[0]][fields[1]] - p2[fields[0]][fields[1]];
});
}
function sortDescendingNumeric(posts, fields) {
posts.sort(function(p1, p2) {
return p2.timestamp - p1.timestamp;
return p2[fields[0]][fields[1]] - p1[fields[0]][fields[1]];
});
}
function sortAscendingAlpha(posts, fields) {
posts.sort(function(p1, p2) {
if (p1[fields[0]][fields[1]] > p2[fields[0]][fields[1]]) return -1;
if (p1[fields[0]][fields[1]] < p2[fields[0]][fields[1]]) return 1;
return 0;
});
}
function sortDescendingAlpha(posts, fields) {
posts.sort(function(p1, p2) {
if (p1[fields[0]][fields[1]] < p2[fields[0]][fields[1]]) return -1;
if (p1[fields[0]][fields[1]] > p2[fields[0]][fields[1]]) return 1;
return 0;
});
}
@ -311,6 +477,10 @@ function searchInTags(query, callback) {
}
function getMainPids(tids, callback) {
if (!Array.isArray(tids) || !tids.length) {
return callback(null, []);
}
topics.getTopicsFields(tids, ['mainPid'], function(err, topics) {
if (err) {
return callback(err);

Loading…
Cancel
Save