deitch/searchjs

Cant match nested Array with false values.

Closed this issue · 3 comments

I'm not sure If I'm missing something or if it is really a bug.
Given data:

const data = [
  {
    cars: [
      {
        exists: true,
        model: "bmw"
      },
      {
        exists: false,
        model: "lada"
      }
    ]
  }
]

I cant seem to match the item when searching for exists: false;
I've tried

{ cars: [{ exists: false }] }
{ "cars.exists": false } // works if searching for true
{ terms: [{ "cars.exists": false }] } // works if searching for true
{ terms: [{ cars: [{ exists: false }] }] }

Demo: https://codesandbox.io/s/y3ow17n9p9

Hi @juanpasolano .

I think there is a bit of misunderstanding here as to how it works.

The matchArray() returns the (possibly empty) list of items at the root of the first argument. In your case, the root array is:

[
  {
    cars: [
      {
        exists: true,
        model: "bmw"
      },
      {
        exists: false,
        model: "lada"
      }
    ]
  }
]

This contains exactly one element, an object with one key cars, and one value an array with two objects in it.

With each of the search terms you gave, it either will match that entire object, or not the entire object (i.e. empty set).

  • { cars: [{ exists: true }] }: This means, "return the single object if it has a key named cars, and its value is one of {exists:true}. This doesn't match, since its value is actually an array with value [{exists: true, model: "bmw"},{exists: false, model: "lada"}], so it fails.
  • { "cars.exists": false }: This uses deep matching, and means, "return the object if there is a key named cars, and it in turn has a property named exists whose value is false, or has a an array which has an object with that value. See here, especially the second example. If it matched, still, the entire cars entry would match. As I think about it, I do believe that this one should match, not just true.
  • { terms: [{ "cars.exists": false }] } : this is just a variant on the second case.
  • { terms: [{ cars: [{ exists: false }] }] }: this is just a variant on the first case.

@deitch thank you so much for the reply, I very much appreciate it. This library is gold!
I, however, failed to explain the issue clearly.

This contains exactly one element, an object with one key cars, and one value an array with two objects in it.

Correct, the idea of the sample was just to have one item of the root array but in reality it would have multiple objects with the same shape.
So a more complete dataset would look like this:

const data = [
  {
    cars: [
      {
        exists: true,
        model: "bmw"
      },
      {
        exists: false,
        model: "lada"
      }
    ]
  },
  {
     cars: [
       {
          exists: true,
          model: "bmw"
       }
     ]
  },
  {...}  //more objects
]

With each of the search terms you gave, it either will match that entire object, or not the entire object (i.e. empty set).

Correct and I am in fact trying to get the entire object.

{ "cars.exists": false }: This uses deep matching, and means, "return the object if there is a key named cars, and it in turn has a property named exists whose value is false, or has a an array which has an object with that value. See here, especially the second example. If it matched, still, the entire cars entry would match. As I think about it, I do believe that this one should match, not just true.

This is exactly what I'd like to achieve but if you see the demo this returns an empty array.
In the example there was only a single object in the array so when failing it will clearly show an empty array (as it currently does).

As I think about it, I do believe that this one should match, not just true.

Right!? And this is the key point of my confusion.

PR would also fix my examples:
https://codesandbox.io/s/kxz8x10nx3