3

Hi I am trying to delete an element which is inside array of array. my schema is :

var mySchema = Schema({ 
  primaryField:String,
  list1: [{
    item1: String,
    item2:String
  }],
  list2 : [{
  item3:String,
    item4 : [String]//item4 is string values available in item1
  }]
});

for ex:

{
  "primaryField": "abc",
  "list1": [{
    "item1": "aa",
    "item2": "mystring"
  },{
    "item1": "bb",
    "item2": "sampStr"
  }],
  "list2": [{
    "item3": "stringitem",
    "item4": ["aa", "bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  },{
    "item3": "samplestring",
    "item4": ["aa"]
  }]
}

I have to delete the "aa" items from list1 and the occurence of "aa" in list2.item4 and if only "aa" is present in item4 then i have to delete the entire object entry.

my output should be:

{
  "primaryField": "abc",
  "list1": [{
    "item1": "bb",
    "item2": "sampStr"
  }],
  list2:[{
    "item3": "stringitem",
    "item4": ["bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  }]
}

could anyone help me to achieve this using node.js and mongoose. Schema cannot be modified.

1 Answer 1

1

This produce the expected output. It should be generic enough, and I'm not sure if it will work with your code, but given what's specified in the question, I think it should be fine.

function removeAllItems(obj, value) {
  var deleted;

  if (!obj) {
    return false;
  }

  if (obj === value) {
    deleted = true;
  } else if (Array.isArray(obj)) {
    for (var i = 0, len = obj.length; i < len; ++i) {
      if (removeAllItems(obj[i], value)) {
        obj.splice(i--, 1);

        if (!obj.length) {
          deleted = true;
        }
      }
    }
  } else if (typeof obj === 'object') {
    for (var keys = Object.keys(obj), key, i = 0, len = keys.length; i < len; ++i) {
      if (removeAllItems(obj[keys[i]], value)) {
        delete obj[keys[i]];

        deleted = true;
      }
    }
  }

  return deleted;
}

Tested with :

var test = {
  "primaryField": "abc",
  "list1": [{
    "item1": "aa",
    "item2": "mystring"
  },{
    "item1": "bb",
    "item2": "sampStr"
  }],
  "list2": [{
    "item3": "stringitem",
    "item4": ["aa", "bb"]
  },{
    "item3": "sample",
    "item4": ["bb"]
  },{
    "item3": "samplestring",
    "item4": ["aa"]
  }]
};

var valueToRemove = 'aa';

removeAllItems(test, valueToRemove);
console.log('Removing all', valueToRemove, JSON.stringify(test, null, 2));

Gives the result

Removing all aa {
  "primaryField": "abc",
  "list1": [
    {
      "item1": "bb",
      "item2": "sampStr"
    }
  ],
  "list2": [
    {
      "item3": "stringitem",
      "item4": [
        "bb"
      ]
    },
    {
      "item3": "sample",
      "item4": [
        "bb"
      ]
    }
  ]
}

Here is an update that take into account cyclical references, and returns true if any value was removed, or false otherwise.

function removeAllItems(obj, value) {
  var stack = [];
  var found = false;

  function _next(obj) {
    var deleted;

    if (!obj) {
      return false;
    } else if (stack.indexOf(obj) >= 0) {
      return false;   // cyclical reference found
    }

    stack.push(obj);

    if (obj === value) {
      found = deleted = true;
    } else if (Array.isArray(obj)) {
      for (var i = 0, len = obj.length; i < len; ++i) {
        if (_next(obj[i])) {
          obj.splice(i--, 1);

          if (!obj.length) {
            deleted = true;
          }
        }
      }
    } else if (typeof obj === 'object') {
      for (var keys = Object.keys(obj), key, i = 0, len = keys.length; i < len; ++i) {
        if (_next(obj[keys[i]])) {
          delete obj[keys[i]];

          deleted = true;
        }
      }
    }

    stack.pop();

    return deleted;
  }

  return _next(obj), found;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply. When i try with the sample data directly it is working fine. But when i pass the output of the find() query [model.find({condition},function(error,result)], it is throwing RangeError : Maximum call stack size exceeded. It would be helpful if you have any idea on this. I am not sure where i am making the mistake in data
Hard to tell without a sample data that produce this error. If you could provide a faulty set, then I'd be able to beter know why you're getting this error. I can try to review my suggestion... but at first glance, it should be fine with what you specified.
Thanks a lot.. It was because i did not convert that to Object (using toObject()). It is working !!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.