使用Lodash使用动态密钥搜索JSON深层嵌套对象?

时间:2018-05-14 19:37:21

标签: javascript lodash

我有一个嵌套的JSON,我想使用lodash进行搜索。如果我正在寻找的搜索词位于某些键内,并且其中一个键是动态的,我如何从data获取根对象?

例如,如果我有:

"data": [
    { 
        "name": "Bob's concourse"
        "activities": [
             {
                 "day": "Monday",
                 "routines":
                     {
                         "Biking": 
                         {
                             "details": "won 3 trophies"
                             "type": "road"
                         },
                         "Kayaking":
                         {
                             "details": "participated in 3 races"
                             "type": "rhythm"
                         }
                      }
                 }
             }
        ]
    },

    {..other_data_etc...},

]
  • activities可以是[];它不能保证它包含任何数据。
  • routines键是动态的。即,BikingKayaking是动态字符串。它可以是任何东西。

如果我想搜索races(不区分大小写),我想专门搜索:

  • data.name
  • data.activities.routines.*(动态键)
  • data.activities.routines.*.details

如果其中任何一个匹配,那么它将返回根对象:{ "name": "Bob", ..... }

我能够让name返回:

function searchText(collection, searchterm) {
    return _.filter(collection, function(o) { 
        return _.includes(o.name.toLowerCase(), searchterm)
    } );
};

但我仍然是lodash的新手,我无法让任何嵌套搜索正确返回,尤其是动态键部分。

有人可以帮忙解释一下解决方案吗?

1 个答案:

答案 0 :(得分:0)

使用lodash扩展您现有的尝试:

const obj = {
  data: [{
    name: 'Bob\'s concourse',
    activities: [{
      day: 'Monday',
      routines: {
        Biking: {
          details: 'won 3 trophies',
          type: 'road'
        },
        Kayaking: {
          details: 'participated in 3 races',
          type: 'rhythm'
        }
      }
    }]
  }]
};

function search(str, data) {
  const searchStr = str.toLowerCase();

  // Only return the entries that contain a matched value
  return _.filter(data, (datum) => {
    // Check if name matches
    return _.includes(datum.name, searchStr)
    || _.some(datum.activities, (activity) => {
        return _.entries(activity.routines).some(([routine, {details}]) => {
          // Check if dynamic routine matches or details
          return _.includes(routine, searchStr) || _.includes(details, searchStr);
        });
      });
  });
}

console.log(search('foobar', obj.data));
console.log(search('races', obj.data));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>

您也可以使用纯JavaScript实现此目的。使用一些新的语法(如destructuring assignment)和新的本机方法(如Object.entries)基本上遵循与使用lodash相同的模式:

const obj = {
  data: [{
    name: 'Bob\'s concourse',
    activities: [{
      day: 'Monday',
      routines: {
        Biking: {
          details: 'won 3 trophies',
          type: 'road'
        },
        Kayaking: {
          details: 'participated in 3 races',
          type: 'rhythm'
        }
      }
    }]
  }]
};

function search(str, data) {
  const regex = RegExp(str, 'i');

  // Only return the entries that contain a matched value
  return data.filter((datum) => {
    // Check if name matches
    return regex.test(datum.name)
    || datum.activities.some((activity) => {
        return Object.entries(activity.routines).some(([routine, {details}]) => {
          // Check if dynamic routine matches or details
          return regex.test(routine) || regex.test(details);
        });
      });
  });
}

console.log(search('foobar', obj.data));
console.log(search('races', obj.data));