kriszyp / lmdb-js

Simple, efficient, ultra-fast, scalable data store wrapper for LMDB
Other
481 stars 39 forks source link

Just an FYI: Improved query/search with lmdb-query getRangeWhere #222

Open anywhichway opened 1 year ago

anywhichway commented 1 year ago

A higher level query mechanism for LMDB supporting functional, declarative and RegExp filters without the overhead of an entire database wrapper: https://www.npmjs.com/package/lmdb-query.

Queries can match against keys, key fragments, values and value fragments and change result values or return just a subset of the top level/renamed/moved properties or nested/renamed/moved properties.

For example:

    db.putSync("person1",{name:"John",age:30,address:{city:"Seattle","stateOrProvince":"WA",country:"US"}});
    db.putSync("person2",{age:30,address:{city:"Seattle","stateOrProvince":"WA",country:"US"}});
    const results = [...db.getRangeWhere(
        ["person"], // match key starting with person
        {name:NOTNULL}, // match object with non-null name
        { // selected values
            age:30, // select age, you could modify this also (age) => age >= 21 ? age - 21 : undefined;
            address:{
                city(value,{root}) { root.city = value.toUpperCase(); }, // selects upper case city into root object
                [/.*(state).*/g]:(value) => value, // selects stateProvince as state because of RegExp group match
                country:ANY
            }
        })];
    // returns [{key:"person1",value:{age:30,city:"SEATTLE",address:{state:"WA",country:"US"}}}]
    expect(results.length).toBe(1);
    expect(results[0].key).toBe("person1");
    expect(results[0].value.name).toBe(undefined);
    expect(results[0].value.age).toBe(30);
    expect(results[0].value.city).toBe("SEATTLE");
    expect(results[0].value.address.state).toBe("WA");
    expect(results[0].value.address.country).toBe("US");

With the exception of the nested address for state and country, in SQL terms, this query would be:

SELECT age, UPPERCASE(address.city) as city
FROM PERSON, ADDRESS WHERE PERSON.id = ADDRESS.personId  AND id="person1" AND name IS NOT NULL AND age = 30
kriszyp commented 1 year ago

This looks really cool, nice work!