3

This is a follow up question from my previous question. From the answer I've received, I am able to search within nested object in an array of objects.

Please find this fiddle for example.

var data = [
{
  'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
  'asset_count': 2,
  'pdg': 'Invalid',
  'user_area': 'Invalid',
  'deployment_number': 'Invalid',
  'spoc': 'invalid',
  'release': 'Invalid',
  'start_date': '2017-06-12 00:00:00',
  'end_date': '2017-06-16 00:00:00',
  'asset_info': [
    {
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',
      
    },
    {
      'bams_id': 'BAMS-1001368001',
      'hostname': 'None',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'HP',
      'model': 'HP BL460C GEN8',
      
    }
],
'full_name': 'Invalid (invalid)',
'email_address': 'Invalid'
},
{
  'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
  'asset_count': 2,
  'pdg': 'Invalid',
  'user_area': 'Invalid',
  'deployment_number': 'Invalid',
  'spoc': 'invalid',
  'release': 'Invalid',
  'start_date': '2017-06-12 00:00:00',
  'end_date': '2017-06-16 00:00:00',
  'asset_info': [
    {
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',
      
    }
],
'full_name': 'Invalid (invalid)',
'email_address': 'Invalid'
}];

Here when I search for a string 'emc', the function returns two objects which is correct. But 'emc' as 'manufacturer' is in child object. And every child object does not satisfies this condition. The result I am looking for, for example 'emc', it should return 2 parent objects. First parent object should have only one child (the other child has 'hp' as manufacturer). Second parent object should have one child as it matches the search string.

I tried to make a new object with search result but couldn't make it work.

How do I return parent object with only child that satisfies the given search string ?

Here is the chatlog on my previous question which can help to understand the problem and requirement.

Community
  • 1
  • 1
Valay
  • 1,991
  • 2
  • 43
  • 98
  • If you do that you won't have the same parent object anymore, since it's children changed. You could add an unique identifier to both parent objects, and return the matching results in a set based on that unique identity though? – Icepickle Jun 15 '17 at 16:00
  • @Icepickle that's fine If I don't have same parent. but object format (keys) should be same. at last I will return new searched data to bind it to the table. – Valay Jun 15 '17 at 16:02

2 Answers2

1

You could use an iterative and recursive approach and return the result of the check and build new objects and arrays if the children matches the search value.

function getValue(item) {
    if (Array.isArray(item)) {
        return item.reduce(iterA, undefined);
    }
    if (item && typeof item === 'object') {
        return iterO(item);
    }
    if (typeof item !== 'object' && item.toString().toLowerCase().indexOf(search) !== -1) {
        return item;
    }
}

function iterO(o) {
    var temp = Object.keys(o).reduce(function (r, k) {
            var value = getValue(o[k]);
            if (value) {
                r = r || {};
                r[k] = value;
            }
            return r;
        }, undefined);

    if (temp) {
        Object.keys(o).forEach(function (k) {
            if (!(k in temp)) {
                temp[k] = o[k];
            }
        });
    }
    return temp;
}

function iterA(r, a) {
    var value = getValue(a);
    if (value) {
        r = r || [];
        r.push(value);
    }
    return r;
}

var data = [{ booking_name: "gtec/1101822/lmikdy/ls-rmea/oss11", asset_count: 2, pdg: "Invalid", user_area: "Invalid", deployment_number: "Invalid", spoc: "invalid", release: "Invalid", start_date: "2017-06-12 00:00:00", end_date: "2017-06-16 00:00:00", asset_info: [{ bams_id: "BAMS-1001423507", hostname: "GTVOSS11", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "EMC", model: "VM" }, { bams_id: "BAMS-1001368001", hostname: "None", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "HP", model: "HP BL460C GEN8" }], full_name: "Invalid (invalid)", email_address: "Invalid" }, { booking_name: "gtec/1101822/lmikdy/ls-rmea/oss11", asset_count: 2, pdg: "Invalid", user_area: "Invalid", deployment_number: "Invalid", spoc: "invalid", release: "Invalid", start_date: "2017-06-12 00:00:00", end_date: "2017-06-16 00:00:00", asset_info: [{ bams_id: "BAMS-1001423507", hostname: "GTVOSS11", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "EMC", model: "VM" }], full_name: "Invalid (invalid)", email_address: "Invalid" }],
    search = 'emc',
    result = data.reduce(iterA, undefined);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

I am unsure how deep your approach need to go, but this should do the trick

it will make a copy of each row when the child item has it, and replace the set with the matching values only

function filterSet(dataSet, matchFn) {
  return dataSet.reduce((current, row) => {
    if (typeof row === 'object') {
      for (let prop in row) {
        if (Array.isArray(row[prop])) {
          var set = filterSet(row[prop], matchFn);
          if (set && set.length > 0) {
            // copy the row, replace the array property with the results
            current.push( Object.assign({}, row,
              { [prop]: set }
            ) );
            // since the full row is now in there
            // no need to check more
            break;
          }
        } else if (matchFn(row[prop])) {
            // copy not ref
            current.push( Object.assign( {}, row ) );
            break;
          }
      }
    }
    return current;
  }, []);
}

var data = [{
    'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
    'asset_count': 2,
    'pdg': 'Invalid',
    'user_area': 'Invalid',
    'deployment_number': 'Invalid',
    'spoc': 'invalid',
    'release': 'Invalid',
    'start_date': '2017-06-12 00:00:00',
    'end_date': '2017-06-16 00:00:00',
    'asset_info': [{
        'bams_id': 'BAMS-1001423507',
        'hostname': 'GTVOSS11',
        'status': 10,
        'site_location': 'IEAT01 Tipperary',
        'rack_number': 'VIRTUAL RACK',
        'rack_u_position': 0,
        'manufacturer': 'EMC',
        'model': 'VM',

      },
      {
        'bams_id': 'BAMS-1001368001',
        'hostname': 'None',
        'status': 10,
        'site_location': 'IEAT01 Tipperary',
        'rack_number': 'VIRTUAL RACK',
        'rack_u_position': 0,
        'manufacturer': 'HP',
        'model': 'HP BL460C GEN8',

      }
    ],
    'full_name': 'Invalid (invalid)',
    'email_address': 'Invalid'
  },
  {
    'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
    'asset_count': 2,
    'pdg': 'Invalid',
    'user_area': 'Invalid',
    'deployment_number': 'Invalid',
    'spoc': 'invalid',
    'release': 'Invalid',
    'start_date': '2017-06-12 00:00:00',
    'end_date': '2017-06-16 00:00:00',
    'asset_info': [{
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',

    }],
    'full_name': 'Invalid (invalid)',
    'email_address': 'Invalid'
  }
];

console.log(filterSet(data, (i) => {
  return i.toString().toLowerCase().indexOf('emc') >= 0;
}));

console.log(filterSet(data, (i) => {
  return i.toString().toLowerCase().indexOf('invalid') >= 0;
}));
Icepickle
  • 12,689
  • 3
  • 34
  • 48