2

I have an object that looks like this:

const inputObject = {
    "startDate": {
        "$gte": "2017-03-29T00:00:00.000Z",
        "$lte": "2017-08-20T00:00:00.000Z"
    },
    "$and": [
        { "$or": [
                {"details.thing": { "$in": [ "01" ] } },
                {"details.thing": { "$in": [ "01" ] } },
                {"details.thing": { "$in" : [ "01" ] } },
                {"details.thing": { "$in" : [ "01" ] } }
            ]
        },
        {
            "$or": []
        },
        {
            "$or": []
        }
    ]
}

I need to develop a function that removes any empty { "$or": [] }, sub-arrays that exist. My intended output is:

const outputObject = {
    "startDate": {
        "$gte": "2017-03-29T00:00:00.000Z",
        "$lte": "2017-08-20T00:00:00.000Z"
    },
    "$and": [
        { "$or": [
                {"details.thing": { "$in": [ "01" ] } },
                {"details.thing": { "$in": [ "01" ] } },
                {"details.thing": { "$in" : [ "01" ] } },
                {"details.thing": { "$in" : [ "01" ] } }
            ]
        }
    ]
}

I'm able to do this for a first level array in the object, but I'm not sure how to do it for a second level one.

2
  • it is always $or? please include the code you tried. Commented Aug 29, 2017 at 16:40
  • Yes, it is always an $or Commented Aug 29, 2017 at 16:43

3 Answers 3

2

use Array.prototype.filter:

const outputObject = {
  "startDate": {
    "$gte": "2017-03-29T00:00:00.000Z",
    "$lte": "2017-08-20T00:00:00.000Z"
  },
  "$and": [
    { 
      "$or": [
        {"details.thing": { "$in": [ "01" ] } },
        {"details.thing": { "$in": [ "01" ] } },
        {"details.thing": { "$in" : [ "01" ] } },
        {"details.thing": { "$in" : [ "01" ] } }
      ]
    },
    {
      "$or": []
    }
  ]
};

var filtered = outputObject.$and = outputObject.$and
  .filter(cond => cond.$or.length > 0)
;

// console.log('filtered', filtered);
// shows only the resulting array, your Object remains
// outputObject
console.log('outputObject', outputObject);

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

4 Comments

This does not work. The output omits the startDate
There is startDate as well
Output is outpuObject not filtered
Run the code snippet. It does not provide the desired outputObject that is shown in the original question. It excludes the "startDate" part completely.
1

You could use an iterative and recursive approach for any depth.

function deepDelete(object, key) {
    Object.keys(object).forEach(function (k) {
        var i;
        if (Array.isArray(object[k])) {
            i = object[k].length;
            while (i--) {
                if (Array.isArray(object[k][i][key]) && object[k][i][key].length === 0) {
                    object[k].splice(i, 1);
                    continue;
                }
                deepDelete(object[k][i], key);
            }
            return;
        }
        if (object[k] && typeof object[k] === 'object') {
            deepDelete(object[k], key) 
        }
    });
}

var data = { startDate: { $gte: "2017-03-29T00:00:00.000Z", $lte: "2017-08-20T00:00:00.000Z" }, $and: [{ $or: [{ "details.thing": { $in: ["01"] } }, { "details.thing": { $in: ["01"] } }, { "details.thing": { $in: ["01"] } }, { "details.thing": { $in: ["01"] } }] }, { $or: [] }, { $or: [] }] };

deepDelete(data, '$or');

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

const inputObject = {
  startDate: {
    $gte: "2017-03-29T00:00:00.000Z",
    $lte: "2017-08-20T00:00:00.000Z"
  },
  $and: [
    {
      $or: [
        { "details.thing": { $in: ["01"] } },
        { "details.thing": { $in: ["01"] } },
        { "details.thing": { $in: ["01"] } },
        { "details.thing": { $in: ["01"] } }
      ]
    },
    {
      $or: []
    },
    {
      $or: []
    }
  ]
};

function isEqualToEmptyOr(obj) {
  return JSON.stringify(obj) === JSON.stringify({ $or: [] });
}

function removeOrRecursion(obj) {
  if (Array.isArray(obj)) {
    let result = [];
    obj.forEach(v => {
      if (!isEqualToEmptyOr(v)) {
        result = result.concat(removeOrRecursion(v));
      }
    });
    return result;
  } else if (typeof obj === "object") {
    let result = {};
    Object.keys(obj).forEach(key => {
      if (!isEqualToEmptyOr(obj[key])) {
        result[key] = removeOrRecursion(obj[key]);
      }
    });
    return result;
  } else {
    return obj;
  }
}

const result = removeOrRecursion(inputObject);
console.log(result);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.