Skip to main content
added 56 characters in body
Source Link
  1. Am I doing this the expected way within the context of JavaScript/Node.js? I.e is there perhaps some built-in I'm unaware of that performs similar logic or could simplify my function?
  2. Is there a more efficient way to perform this in JavaScript?
  3. Is there anything my function isn't taking into consideration, missing in general or overlooking when taking this approach?
  4. Is it a bad idea to use recursion here forwith the anon function declared in the function when considering sub-objects in the filter? If so, why?
  5. Any other comments / constructive criticism you might have.
  1. Am I doing this the expected way within the context of JavaScript/Node.js? I.e is there perhaps some built-in I'm unaware of that performs similar logic or could simplify my function?
  2. Is there a more efficient way to perform this in JavaScript?
  3. Is there anything my function isn't taking into consideration, missing in general or overlooking when taking this approach?
  4. Is it a bad idea to use recursion here for considering sub-objects in the filter?
  5. Any other comments / constructive criticism you might have.
  1. Am I doing this the expected way within the context of JavaScript/Node.js? I.e is there perhaps some built-in I'm unaware of that performs similar logic or could simplify my function?
  2. Is there a more efficient way to perform this in JavaScript?
  3. Is there anything my function isn't taking into consideration, missing in general or overlooking when taking this approach?
  4. Is it a bad idea to use recursion with the anon function declared in the function when considering sub-objects in the filter? If so, why?
  5. Any other comments / constructive criticism you might have.
Source Link

Implementation of a schema-less `AND` query in Node.js against array of objects

Note: I'm still very new to the code-review stack exchange, so if this question does not align with the community guidelines please leave a comment below explaining and I will do my best to modify it to adhere to the community guidelines.

Explanation

I'm attempting to implement a filter() function that functions most similarly to (I might be wrong in my understanding here) a WHERE query on a schema-less database that only allows for AND operators when concatenating WHERE clauses (no OR), and = operators for comparison (no <, >, CONTAINS, etc. operators).

Requirements

I hope this describes the functions expected behavior well enough.

The function should take in an array of objects and a filter. It should return objects within the array that are considered valid within the context of the filter. The filter is a subset of key/values that MUST be present in each object for them to be considered valid within the context of the filter.

Simple Example

Given the data:

const data = [
    {
        name: 'John',
        age: 10
    },
    {
        name: 'Jill',
        age: 15
    },
    {
        name: 'Jack',
        age: 10
    }
];

And the filter:

{
    age: 10
}

The results would look like:

[
    {
        name: 'John',
        age: 10
    },
    {
        name: 'Jack',
        age: 10
    }
]

Code I'd like reviewed

Currently, my function looks like this:

Keep in mind I allow the data to also be an object, in which case we get the data array using Object.values(data);. This is a requirement of the project I'm implementing this function in. So, please ignore the first few lines of the function and just consider that data is always an Array.

function filter(data, f) {
    // Make sure we're dealing with an array, if an object is passed,
    // just consider it's values.

    let finalData;

    if (Array.isArray(data)) {
        finalData = data;
    }
    
    if (finalData === undefined && typeof data === 'object') {
        finalData = Object.values(data);
    }

    if (finalData === undefined) {
        throw new Error('Data being filtered must be either an Array or an Object.');
    }

    // Define a function to use for filtering the object. This may use recurrsion if one of
    // the values in the filter is another object.

    const isInFilter = (obj, f) => {
        let filterTermsMet = true;
        for (const filteredProp in f) {
            filterTermsMet = (typeof f[filteredProp] === 'object' && !Array.isArray(f[filteredProp]))
                ? isInFilter(obj[filteredProp], f[filteredProp])
                : obj[filteredProp] === f[filteredProp];
    
            if (!filterTermsMet) {
                break;
            }
        }
    
        return filterTermsMet;
    }

    // Perform the filter on the final object and return the result.

    return finalData.filter(element => {
        return isInFilter(element, f);
    });
};

Review I'm looking for / Questions I have of peers

Please bear in mind that I'm relatively new to JavaScript/Node.js.

  1. Am I doing this the expected way within the context of JavaScript/Node.js? I.e is there perhaps some built-in I'm unaware of that performs similar logic or could simplify my function?
  2. Is there a more efficient way to perform this in JavaScript?
  3. Is there anything my function isn't taking into consideration, missing in general or overlooking when taking this approach?
  4. Is it a bad idea to use recursion here for considering sub-objects in the filter?
  5. Any other comments / constructive criticism you might have.

More Complex Examples

Input Data

const objectsArr = [
    {
        name: 'John',
        age: 25,
        physical: {
            height: 6.2,
            weight: 200
        }
    },
    {
        name: 'Jason',
        age: 24,
        physical: {
            height: 6.0,
            weight: 200
        }
    },
    {
        name: 'Jenny',
        age: 25,
        physical: {
            height: 5.3,
            weight: 105
        }
    },
    {
        name: 'Kevin',
        age: 21,
        physical: {
            height: 5.3,
            weight: 189
        }
    },
    {
        name: 'Phil',
        age: 24,
        physical: {
            height: 6.0,
            weight: 189
        }
    }
];

Run Filters

let filterToUse;

filterToUse = { // normal condition
    age: 25
};
console.log(filterToUse, filter(objectsArr, filterToUse).map(person => person.name));

filterToUse = { // sub-object condition
    physical: {
        weight: 200
    }
};
console.log(filterToUse, filter(objectsArr, filterToUse).map(person => person.name));

filterToUse = { // alternate sub-object condition
    physical: {
        height: 5.3
    }
};
console.log(filterToUse, filter(objectsArr, filterToUse).map(person => person.name));

filterToUse = { // sub-object condition, multiple conditions (AND)
    age: 24,
    physical: {
        height: 6.0
    }
};
console.log(filterToUse, filter(objectsArr, filterToUse).map(person => person.name));

Results

{ age: 25 } [ 'John', 'Jenny' ]
{ physical: { weight: 200 } } [ 'John', 'Jason' ]
{ physical: { height: 5.3 } } [ 'Jenny', 'Kevin' ]
{ age: 24, physical: { height: 6 } } [ 'Jason', 'Phil' ]