mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-05 12:01:17 +01:00
user search changes
This commit is contained in:
@@ -2,65 +2,198 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
meta = require('../meta'),
|
||||
user = require('../user'),
|
||||
db = require('../database');
|
||||
|
||||
module.exports = function(User) {
|
||||
|
||||
User.search = function(data, callback) {
|
||||
var query = data.query;
|
||||
var by = data.by || 'username';
|
||||
var searchBy = data.searchBy || ['username'];
|
||||
var startsWith = data.hasOwnProperty('startsWith') ? data.startsWith : true;
|
||||
var page = data.page || 1;
|
||||
|
||||
if (!query || query.length === 0) {
|
||||
return callback(null, {timing:0, users:[]});
|
||||
if (!query) {
|
||||
return callback(null, {timing: 0, users: [], matchCount: 0, pages: []});
|
||||
}
|
||||
|
||||
if (by === 'ip') {
|
||||
if (searchBy === 'ip') {
|
||||
return searchByIP(query, callback);
|
||||
}
|
||||
|
||||
var start = process.hrtime();
|
||||
var key = by + ':uid';
|
||||
var startTime = process.hrtime();
|
||||
var keys = searchBy.map(function(searchBy) {
|
||||
return searchBy + ':uid';
|
||||
});
|
||||
|
||||
db.getObject(key, function(err, hash) {
|
||||
if (err || !hash) {
|
||||
return callback(null, {timing: 0, users:[]});
|
||||
var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20;
|
||||
var start = Math.max(0, page - 1) * resultsPerPage;
|
||||
var end = start + resultsPerPage;
|
||||
var pageCount = 1;
|
||||
var matchCount = 0;
|
||||
var filterBy = Array.isArray(data.filterBy) ? data.filterBy : [];
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
findUids(query, keys, startsWith, next);
|
||||
},
|
||||
function(uids, next) {
|
||||
filterAndSortUids(uids, filterBy, data.sortBy, next);
|
||||
},
|
||||
function(uids, next) {
|
||||
matchCount = uids.length;
|
||||
uids = uids.slice(start, end);
|
||||
|
||||
User.getUsers(uids, next);
|
||||
},
|
||||
function(userData, next) {
|
||||
|
||||
var pages = [];
|
||||
if (matchCount > resultsPerPage) {
|
||||
pageCount = Math.ceil(matchCount / resultsPerPage);
|
||||
var currentPage = Math.max(1, Math.ceil((start + 1) / resultsPerPage));
|
||||
for(var i=1; i<=pageCount; ++i) {
|
||||
pages.push({page: i, active: i === currentPage});
|
||||
}
|
||||
}
|
||||
|
||||
var diff = process.hrtime(startTime);
|
||||
var timing = (diff[0] * 1e3 + diff[1] / 1e6).toFixed(1);
|
||||
next(null, {
|
||||
timing: timing,
|
||||
users: userData,
|
||||
matchCount: matchCount,
|
||||
pages: pages
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
function findUids(query, keys, startsWith, callback) {
|
||||
db.getObjects(keys, function(err, hashes) {
|
||||
if (err || !hashes) {
|
||||
return callback(err, []);
|
||||
}
|
||||
|
||||
hashes = hashes.filter(Boolean);
|
||||
|
||||
query = query.toLowerCase();
|
||||
|
||||
var values = Object.keys(hash);
|
||||
var uids = [];
|
||||
var resultsPerPage = parseInt(meta.config.userSearchResultsPerPage, 10) || 20;
|
||||
var hardCap = resultsPerPage * 10;
|
||||
|
||||
for(var i=0; i<values.length; ++i) {
|
||||
if (startsWith) {
|
||||
if (values[i].toLowerCase().indexOf(query) === 0) {
|
||||
uids.push(values[i]);
|
||||
for(var i=0; i<hashes.length; ++i) {
|
||||
for(var field in hashes[i]) {
|
||||
if ((startsWith && field.toLowerCase().startsWith(query)) || (!startsWith && field.toLowerCase().indexOf(query) !== -1)) {
|
||||
uids.push(hashes[i][field]);
|
||||
if (uids.length >= hardCap) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (values[i].toLowerCase().indexOf(query) !== -1) {
|
||||
uids.push(values[i]);
|
||||
}
|
||||
|
||||
if (uids.length >= hardCap) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uids = uids.slice(0, 20)
|
||||
.sort(function(a, b) {
|
||||
return a > b;
|
||||
})
|
||||
.map(function(username) {
|
||||
return hash[username];
|
||||
if (hashes.length > 1) {
|
||||
uids = uids.filter(function(uid, index, array) {
|
||||
return array.indexOf(uid) === index;
|
||||
});
|
||||
}
|
||||
|
||||
User.getUsers(uids, function(err, userdata) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var diff = process.hrtime(start);
|
||||
var timing = (diff[0] * 1e3 + diff[1] / 1e6).toFixed(1);
|
||||
callback(null, {timing: timing, users: userdata});
|
||||
});
|
||||
callback(null, uids);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function filterAndSortUids(uids, filterBy, sortBy, callback) {
|
||||
sortBy = sortBy || 'joindate';
|
||||
|
||||
var fields = filterBy.map(function(filter) {
|
||||
return filter.field;
|
||||
}).concat(['uid', sortBy]).filter(function(field, index, array) {
|
||||
return array.indexOf(field) === index;
|
||||
});
|
||||
|
||||
async.parallel({
|
||||
userData: function(next) {
|
||||
user.getMultipleUserFields(uids, fields, next);
|
||||
},
|
||||
isOnline: function(next) {
|
||||
if (fields.indexOf('status') !== -1) {
|
||||
require('../socket.io').isUsersOnline(uids, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var userData = results.userData;
|
||||
|
||||
if (results.isOnline) {
|
||||
userData.forEach(function(userData, index) {
|
||||
userData.status = user.getStatus(userData.status, results.isOnline[index]);
|
||||
});
|
||||
}
|
||||
|
||||
userData = filterUsers(userData, filterBy);
|
||||
|
||||
sortUsers(userData, sortBy);
|
||||
|
||||
uids = userData.map(function(user) {
|
||||
return user && user.uid;
|
||||
});
|
||||
callback(null, uids);
|
||||
});
|
||||
}
|
||||
|
||||
function filterUsers(userData, filterBy) {
|
||||
function passesFilter(user, filter) {
|
||||
if (!user || !filter) {
|
||||
return false;
|
||||
}
|
||||
var userValue = user[filter.field];
|
||||
if (filter.type === '=') {
|
||||
return userValue === filter.value;
|
||||
} else if (filter.type === '!=') {
|
||||
return userValue !== filter.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filterBy.length) {
|
||||
return userData;
|
||||
}
|
||||
|
||||
return userData.filter(function(user) {
|
||||
for(var i=0; i<filterBy.length; ++i) {
|
||||
if (!passesFilter(user, filterBy[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function sortUsers(userData, sortBy) {
|
||||
userData.sort(function(user1, user2) {
|
||||
if (sortBy === 'joindate' || sortBy === 'postcount') {
|
||||
return user2[sortBy] - user1[sortBy];
|
||||
} else {
|
||||
if(user1[sortBy] < user2[sortBy]) {
|
||||
return -1;
|
||||
} else if(user1[sortBy] > user2[sortBy]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function searchByIP(ip, callback) {
|
||||
var start = process.hrtime();
|
||||
|
||||
Reference in New Issue
Block a user