5

There is an array of objects (489 objects). An object has a key which has another object (child object). Number of child object is indefinite.

I've created a fiddle as well. Please find below search function:

function getObjects(obj, key, val) {
    var objects = [];
    for (var i in obj) {
        if (!obj.hasOwnProperty(i)) continue;
        if (typeof obj[i] == 'object') {
            parent = obj;
            objects = objects.concat(getObjects(obj[i], key, val));    
        } else {
            if(obj[i].toString().toLowerCase().indexOf(val.toString().toLowerCase()) > -1) {
                objects.push(obj);
            }
        } 
    }
    return objects;
} 

Here I want to search for a search string in an array of object including nested object (asset_info) as well. The search without getObjects works fine with below function.

    this.data.filter(function(row){ 
        var flag; 
        for(var prop in (columns.length > 0 ? columns : row)){ 
          flag = false; 
          flag = row[columns.length > 0 ? columns[prop] : 
prop].toString().toLowerCase().indexOf(searchString.toString().toLowerCase()) > -1; 
          if(flag) 
          break; 
        } 
    return flag;

In above function I am not able to search within nested object (asset_info). And so I have been using getObject function which I found online.

Now the issue is I am not able to search including asset_info but not able to return its parent. For example in fiddle, if I search for emc, search should return 2nd object from data.

Update: still not able to return parent of a child where search string has been found

** Update 2 **

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 if I search for a string 'emc', it should return 2 objects. 1st object will have only one child as there is only one object has 'manufacturer' as 'emc'.

The output should be:

[
{
  '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'
},
{
  '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'
}];

How do I search for a string within an array of objects including nested object and return parent object if search string is found in child object ?

2

1 Answer 1

5

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; }

Sign up to request clarification or add additional context in comments.

13 Comments

that's great. it works fine. thanks a lot. how can I return parent with only child/children that has search string ? I mean not returning all child even if search string has been found in only one child.
do you mean the parent object?
yes parent with only child that has search string found.
for example if search string has found within 2 child out of 20 children, the function should return parent with 2 child only. currently it's returning parent with all 20 children.
I've updated data in fiddle jsfiddle.net/7eL7t0d1/7. If I search for string 'emc', function should return 2 objects. first object should have only one child where manufacturer is emc.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.