kentcdodds / match-sorter

Simple, expected, and deterministic best-match sorting of an array in JavaScript
https://npm.im/match-sorter
MIT License
3.73k stars 129 forks source link

Nested keys not matching others in the array #82

Closed skube closed 4 years ago

skube commented 4 years ago

The example provided in the docs is as follows (and only has one item in each name array):

const nestedObjList = [
  {name: [{first: 'Janice'}]},
  {name: [{first: 'Fred'}]},
  {name: [{first: 'George'}]},
  {name: [{first: 'Jen'}]},
]
matchSorter(nestedObjList, 'j', {keys: ['name.0.first']})
// [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}]

I have a similar structure, however mine only seems to match the first entry in the array.

const nestedObjList = [
  {name: [{first: 'Janice', last: 'Smith'}, {first: 'Jon', last: 'Doe'}]},
  {name: [{first: 'Fred', last: 'Astaire'}, {first: 'Jenny', last: 'Doe'}, {first: 'Wilma', last: 'Flintstone'}]},
]
matchSorter(nestedObjList, 'j', {keys: ['name.0.first', 'name.0.last]})
// [{name: {first: 'Janice'}}]
// Where's Jenny?! 🤔

Am I doing something wrong?

kentcdodds commented 4 years ago

name.0.first will allow you to match Janice or Fred with that data. This is because the 0 in that key string is referencing the first entry in the name array of each object.

If you want to match any of the number of arrays, then you should use the property callback. Here's the example from the docs:

const list = [{name: 'Janice'}, {name: 'Fred'}, {name: 'George'}, {name: 'Jen'}]
matchSorter(list, 'j', {keys: [item => item.name]})
// [{name: 'Janice'}, {name: 'Jen'}]
skube commented 4 years ago

Thanks for responding. Your example does work for only one property. I must be dense because I still can't get it work with more complicated structures.

I've created a sandbox to illustrate

skube commented 4 years ago

A co-worker actually figured it out, so given:

  const nestedObjList = [
    {
      name: [
       { first: 'Janice', last: 'Smith' },
       { first: 'Jon', last: 'Doe' }
      ],
    },
    {
      name: [
        { first: 'Fred', last: 'Astaire' },
        { first: 'Jenny', last: 'Doe' },
        { first: 'Wilma', last: 'Flintstone' },
      ],
    },
  ];

You need to use map:

 matchSorter(nestedObjList, 'doe', {
          keys: [
            item => item.name.map(i => i.first),
            item => item.name.map(i => i.last),
          ],
        })

@kentcdodds I would recommend updating the docs to make it more clear for this kind of use case. 😃

skube commented 4 years ago

I've created a PR to hopefully help.