Now the expectation is to have only [x y z h r s] is the final result. But mongodb assumes {"names" : "a", "value": "something"} and {"value": "something", "names" : "a"} are two different values even though they are identical.
Is this a bug? Are there any workarounds for this? (My actual data has 5 fields so being in a different order is more likely imo)
No it is not a bug. Operations like $setDifference and $setIntersection are based on value equality. Two objects are equals if the have same fields and same values in the same order.
Normalize your data so that fields are in the same order. Since objects are usually updated using an application or an API, having the fields in the same order is usually not an issue. The issue arise when human update the values or when code is broken and objects are updated directly rather than a data access layer.
The goal is to find out of any of the a: have the wrong order. The correct order is to have foo: first and then bar:. In the collection above _id:0 has the correct order and _id:3 has not.
The first stage will set the field _a: using $objectToArray on a: