Skip to content

Queries on relation fields with multiple ins do not work correctly. #1271

@jyoon17

Description

@jyoon17

For implementation related questions or technical support, please refer to the Stack Overflow and Server Fault communities.

Make sure these boxes are checked before submitting your issue -- thanks for reporting issues back to Parse Server!

Steps to reproduce

  • See "queries on relation fields with multiple ins" case in ParseRelation.spec.js

    • The expected number of results must be zero not two. The case is incorrect.
    it("queries on relation fields with multiple ins", (done) => {
        var ChildObject = Parse.Object.extend("ChildObject");
        var childObjects = [];
        for (var i = 0; i < 10; i++) {
          childObjects.push(new ChildObject({x: i}));
        }
    
        Parse.Object.saveAll(childObjects).then(() => {
          var ParentObject = Parse.Object.extend("ParentObject");
          var parent = new ParentObject();
          parent.set("x", 4);
          var relation = parent.relation("child");
          relation.add(childObjects[0]);
          relation.add(childObjects[1]);
          relation.add(childObjects[2]);
          var parent2 = new ParentObject();
          parent2.set("x", 3);
          var relation2 = parent2.relation("child");
          relation2.add(childObjects[4]);
          relation2.add(childObjects[5]);
          relation2.add(childObjects[6]);
    
          var otherChild2 = parent2.relation("otherChild");
          otherChild2.add(childObjects[0]);
          otherChild2.add(childObjects[1]);
          otherChild2.add(childObjects[2]);
    
          var parents = [];
          parents.push(parent);
          parents.push(parent2);
          return Parse.Object.saveAll(parents);
        }).then(() => {
          var query = new Parse.Query(ParentObject);
          var objects = [];
          objects.push(childObjects[0]);
          query.containedIn("child", objects);
          query.containedIn("otherChild", [childObjects[0]]);
          return query.find();
        }).then((list) => {
          equal(list.length, 2, "There should be 2 results");
          done();
        });
      });

Logs/Trace

  • The actual REST request generated by the case

    {
      "where": {
        "child": {
          "$in": [
            {
              "__type": "Pointer",
              "className": "ChildObject",
              "objectId": "t4EmF6vnq5"
            }
          ]
        },
        "otherChild": {
          "$in": [
            {
              "__type": "Pointer",
              "className": "ChildObject",
              "objectId": "t4EmF6vnq5"
            }
          ]
        }
      },
      "_method": "GET"
    }

Causes

DatabaseController.prototype.addInObjectIdsIds = function(ids, query) {
  if (typeof query.objectId == 'string') {
    // Add equality op as we are sure
    // we had a constraint on that one
    query.objectId = {'$eq': query.objectId};
  }
  query.objectId = query.objectId || {};
  let queryIn =  [].concat(query.objectId['$in'] || [], ids || []);
  // make a set and spread to remove duplicates
  // replace the $in operator as other constraints
  // may be set
  query.objectId['$in'] = [...new Set(queryIn)];

  return query;
}
  • multiple $ins on different relation fields end up having a merged $in on objectId

    {
      "child": {
        "$in": [
          "pointer to child0"
        ]
      },
      "otherChild": {
        "$in": [
          "pointer to child0"
        ]
      }
    }

    becomes

    {
      "objectId": {
        "$in": [
          "objectId of parent",
          "objectId of parent2"
        ]
      }
    }

    It is supposed to be like

    {
      "$and": [
        {
          "objectId": {
            "$in": [
              "objectId of parent"
            ]
          }
        },
        {
          "objectId": {
            "$in": [
              "objectId of parent2"
            ]
          }
        }
      ]
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions