feat: fullname search (#8641)

* feat: fullname search

* fix: take last element

* fix: attempt to fix psql like query

* feat: upgrade sript, another fix attempt

* fix: psql test

* fix: psql scan

* feat: add debug for test

* feat: test collate

* feat: cleanup

* fix: upgrade script
v1.18.x
Barış Soner Uşaklı 5 years ago committed by GitHub
parent 9389749b79
commit 4be693f2e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,7 +42,7 @@ usersController.search = async function (req, res) {
match: query,
limit: hardCap,
});
return data.map(data => data.split(':')[1]);
return data.map(data => data.split(':').pop());
},
});

@ -582,15 +582,15 @@ DELETE FROM "legacy_zset" z
if (min.match(/^\(/)) {
q.values.push(min.substr(1));
q.suffix += 'GT';
q.where += ` AND z."value" > $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" > $` + q.values.length + `::TEXT COLLATE "C"`;
} else if (min.match(/^\[/)) {
q.values.push(min.substr(1));
q.suffix += 'GE';
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT COLLATE "C"`;
} else {
q.values.push(min);
q.suffix += 'GE';
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" >= $` + q.values.length + `::TEXT COLLATE "C"`;
}
}
@ -598,15 +598,15 @@ DELETE FROM "legacy_zset" z
if (max.match(/^\(/)) {
q.values.push(max.substr(1));
q.suffix += 'LT';
q.where += ` AND z."value" < $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" < $` + q.values.length + `::TEXT COLLATE "C"`;
} else if (max.match(/^\[/)) {
q.values.push(max.substr(1));
q.suffix += 'LE';
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT COLLATE "C"`;
} else {
q.values.push(max);
q.suffix += 'LE';
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT`;
q.where += ` AND z."value" <= $` + q.values.length + `::TEXT COLLATE "C"`;
}
}

@ -0,0 +1,26 @@
'use strict';
const db = require('../../database');
const batch = require('../../batch');
const user = require('../../user');
module.exports = {
name: 'Create fullname search set',
timestamp: Date.UTC(2020, 8, 11),
method: async function () {
const progress = this.progress;
await batch.processSortedSet('users:joindate', async function (uids) {
progress.incr(uids.length);
const userData = await user.getUsersFields(uids, ['uid', 'fullname']);
const bulkAdd = userData
.filter(u => u.uid && u.fullname)
.map(u => ['fullname:sorted', 0, u.fullname.toLowerCase() + ':' + u.uid]);
await db.sortedSetAddBulk(bulkAdd);
}, {
batch: 500,
progress: this.progress,
});
},
};

@ -94,6 +94,10 @@ module.exports = function (User) {
bulkAdd.push(['user:' + userData.uid + ':emails', timestamp, userData.email + ':' + timestamp]);
}
if (userData.fullname) {
bulkAdd.push(['fullname:sorted', 0, userData.fullname.toLowerCase() + ':' + userData.uid]);
}
await Promise.all([
db.incrObjectField('global', 'userCount'),
db.sortedSetAddBulk(bulkAdd),

@ -136,6 +136,10 @@ module.exports = function (User) {
bulkRemove.push(['email:sorted', userData.email.toLowerCase() + ':' + uid]);
}
if (userData.fullname) {
bulkRemove.push(['fullname:sorted', userData.fullname.toLowerCase() + ':' + uid]);
}
await Promise.all([
db.sortedSetRemoveBulk(bulkRemove),
db.decrObjectField('global', 'userCount'),

@ -263,6 +263,14 @@ module.exports = function (User) {
async function updateFullname(uid, newFullname) {
const fullname = await User.getUserField(uid, 'fullname');
await updateUidMapping('fullname', uid, newFullname, fullname);
if (newFullname !== fullname) {
if (fullname) {
await db.sortedSetRemove('fullname:sorted', fullname.toLowerCase() + ':' + uid);
}
if (newFullname) {
await db.sortedSetAdd('fullname:sorted', 0, newFullname.toLowerCase() + ':' + uid);
}
}
}
User.changePassword = async function (uid, data) {

@ -63,7 +63,7 @@ module.exports = function (User) {
hardCap = hardCap || resultsPerPage * 10;
const data = await db.getSortedSetRangeByLex(searchBy + ':sorted', min, max, 0, hardCap);
const uids = data.map(data => data.split(':')[1]);
const uids = data.map(data => data.split(':').pop());
return uids;
}

@ -399,6 +399,22 @@ describe('User', function () {
});
});
it('should search users by fullname', async function () {
const uid = await User.create({ username: 'fullnamesearch1', fullname: 'Mr. Fullname' });
const data = await socketUser.search({ uid: adminUid }, { query: 'mr', searchBy: 'fullname' });
assert(Array.isArray(data.users));
assert.equal(data.users.length, 1);
assert.equal(uid, data.users[0].uid);
});
it('should search users by fullname', async function () {
const uid = await User.create({ username: 'fullnamesearch2', fullname: 'Baris:Usakli' });
const data = await socketUser.search({ uid: adminUid }, { query: 'baris:', searchBy: 'fullname' });
assert(Array.isArray(data.users));
assert.equal(data.users.length, 1);
assert.equal(uid, data.users[0].uid);
});
it('should return empty array if query is empty', function (done) {
socketUser.search({ uid: testUid }, { query: '' }, function (err, data) {
assert.ifError(err);

Loading…
Cancel
Save