You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/user/search.js

171 lines
4.1 KiB
JavaScript

'use strict';
10 years ago
var async = require('async'),
meta = require('../meta'),
pagination = require('../pagination'),
plugins = require('../plugins'),
10 years ago
db = require('../database');
module.exports = function(User) {
10 years ago
User.search = function(data, callback) {
10 years ago
var query = data.query || '';
var searchBy = data.searchBy || 'username';
var page = data.page || 1;
var uid = data.uid || 0;
var paginate = data.hasOwnProperty('paginate') ? data.paginate : true;
if (searchBy.indexOf('ip') !== -1) {
return searchByIP(query, uid, callback);
10 years ago
}
var startTime = process.hrtime();
var searchResult = {};
async.waterfall([
function(next) {
if (data.findUids) {
data.findUids(query, searchBy, next);
} else {
findUids(query, searchBy, next);
}
},
function(uids, next) {
filterAndSortUids(uids, data, next);
},
function(uids, next) {
plugins.fireHook('filter:users.search', {uids: uids, uid: uid}, next);
},
function(data, next) {
var uids = data.uids;
searchResult.matchCount = uids.length;
if (paginate) {
var pagination = User.paginate(page, uids);
uids = pagination.data;
searchResult.pagination = pagination.pagination;
10 years ago
searchResult.pageCount = pagination.pageCount;
}
User.getUsers(uids, uid, next);
},
function(userData, next) {
searchResult.timing = (process.elapsedTimeSince(startTime) / 1000).toFixed(2);
searchResult.users = userData;
next(null, searchResult);
}
], callback);
};
10 years ago
User.paginate = function(page, data) {
var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20;
var start = Math.max(0, page - 1) * resultsPerPage;
var stop = start + resultsPerPage;
var pageCount = Math.ceil(data.length / resultsPerPage);
var currentPage = Math.max(1, Math.ceil((start + 1) / resultsPerPage));
return {
pagination: pagination.create(currentPage, pageCount),
10 years ago
pageCount: pageCount,
data: data.slice(start, stop)
};
};
function findUids(query, searchBy, callback) {
if (!query) {
return callback(null, []);
}
var min = query;
var max = query.substr(0, query.length - 1) + String.fromCharCode(query.charCodeAt(query.length - 1) + 1);
var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20;
var hardCap = resultsPerPage * 10;
db.getSortedSetRangeByLex(searchBy + ':sorted', min, max, 0, hardCap, function(err, data) {
if (err) {
return callback(err);
}
var uids = data.map(function(data) {
return data.split(':')[1];
});
callback(null, uids);
});
}
function filterAndSortUids(uids, data, callback) {
var sortBy = data.sortBy || 'joindate';
var fields = ['uid', 'status', sortBy];
async.parallel({
userData: function(next) {
User.getMultipleUserFields(uids, fields, next);
},
isOnline: function(next) {
if (data.onlineOnly) {
require('../socket.io').isUsersOnline(uids, next);
} else {
next();
}
}
}, function(err, results) {
if (err) {
return callback(err);
}
var userData = results.userData;
11 years ago
if (data.onlineOnly) {
userData = userData.filter(function(user, index) {
return user && user.status !== 'offline' && results.isOnline[index];
});
}
sortUsers(userData, sortBy);
uids = userData.map(function(user) {
return user && user.uid;
});
callback(null, uids);
});
}
function sortUsers(userData, sortBy) {
10 years ago
if (sortBy === 'joindate' || sortBy === 'postcount') {
userData.sort(function(u1, u2) {
return u2[sortBy] - u1[sortBy];
});
} else {
userData.sort(function(u1, u2) {
if(u1[sortBy] < u2[sortBy]) {
return -1;
10 years ago
} else if(u1[sortBy] > u2[sortBy]) {
return 1;
}
return 0;
10 years ago
});
}
}
10 years ago
function searchByIP(ip, uid, callback) {
10 years ago
var start = process.hrtime();
async.waterfall([
function(next) {
db.getSortedSetRevRange('ip:' + ip + ':uid', 0, -1, next);
},
function(uids, next) {
User.getUsers(uids, uid, next);
10 years ago
},
function(users, next) {
var diff = process.hrtime(start);
var timing = (diff[0] * 1e3 + diff[1] / 1e6).toFixed(1);
next(null, {timing: timing, users: users});
}
], callback);
}
};