Minato Namikaze
Minato Namikaze

Reputation: 606

MongoDB encrypted field partial search

Is it possible to partial search(like/regex query) on an encrypted field in mongodb?

I have a field which contains encrypted email id. So in mongo the email [email protected] becomes 1bcuh6762jhjdSOME_ENCRYPTED_VALUE, now is it possible to do partial search on this encrypted value

Upvotes: 1

Views: 2157

Answers (1)

Muhammad Faizan
Muhammad Faizan

Reputation: 1789

I came across a similar problem i resolved it, by creating hash of all possible values that were more than 3 letters. and created hash for all possible combinations, you can add the value to be set with pre('save').

In Schema You can create this function:

function createHash(next) {
    this.hashes = hash.createHashForField(this.text);
    debug(text);
    next();
}

mySchema.pre('save', createHash);

A module for hashing hash.js

const hash = require('crypto');
const adler32 = require('adler32');
const crypto = require('crypto');
const _  = require('lodash');
adler32.register();

module.exports = Hash = {
    /**
     * This method creates hash of given text;
     * @param text - text to hash;
     */
    createHash: (text) => {
        return crypto.createHash('adler32').update(text, 'ascii').digest('hex');
    },
    /**
     *
     * @param text- text separated by spaces
     */
    createHashForText: (text) => {
        "use strict";
        text= text.toLowerCase();
        text= text.trim();
        let textSlices = _.flatten(text.split(' ').filter(x => x.length)
          .map((part) => {
            if (part.length < 3) {
                return part;
            }
            let nameSlices = [];
            for (let index = 2; index < part.length; index ++) {
                let n = part.slice(0, index+1);
                textSlices .push(n);
            }
            return textSlices ;
        }));

        return textSlices .map(n => Hash.createHash(n));
    }
}

after that you can migrate all your records like this:

myModel.find({}).then(docs => {
    docs.forEach(doc => doc.save().catch(console.log))
})

Now when search, You will have to use createHash function to make hash of keyword and search it in your database.

I hope this helps.

Upvotes: 3

Related Questions