解析Cloud Code语法差异导致查询失败

时间:2019-01-31 02:57:43

标签: javascript mongodb aggregation-framework parse-server

我们需要使用多个阶段的聚集管线,例如:addFieldslookupgroupunwind。将MongoDB罗盘中的工作语法转换为解析云代码javascript调用时,我们不会得到相同的结果。

从MongoDB指南针导出的“节点”代码如下:

[
  {
    '$addFields': {
      'user': {
        '$substr': [
          '$_p_pUser', 6, -1
        ]
      }
    }
  }, {
    '$lookup': {
      'from': '_User', 
      'localField': 'user', 
      'foreignField': '_id', 
      'as': 'userobject'
    }
  }, {
    '$addFields': {
      'username': '$userobject.username'
    }
  }, {
    '$unwind': {
      'path': '$username'
    }
  }, {
    '$group': {
      '_id': '$username', 
      'total': {
        '$sum': '$score'
      }
    }
  }
]

原始mongoDB查询与来自解析服务器的调用所需的语法之间存在明显的语法差异。据我所知,转换为应该可以使用的语法如下:

var pipeline = 
    {
        addFields : 
        { 
            user : '$pUser.objectId', // different from the above syntax. This is how the object id of the user is accessed
            username: '$userobject.username'
        },
        lookup : {
            from: '_User',
            localField: 'user',
            foreignField: '_id', // although most calls from the parse server aggregate pipeline should access "_is" instead by "objectId", in this case it seems the lookup table has a field name "_id" and not "objectId"
            as: 'userobject'
        },
        unwind : { path: '$username' },
        group : {
            objectId: '$username',
            total : {
              $sum : '$score'
            }
        }
    };
    var pipelineResults = await gameTableQuery.aggregate(pipeline);

预期产量

预期输出将使当前表的用户指针(pUser)与User表匹配。然后按用户名分组,同时找到总分。

实际输出

在上述情况下,在查找阶段搜索_id时,返回0个条目。

在用objectId替换查找阶段foreignField的情况下,每个用户,而不仅仅是匹配本地字段的用户。

lookup : {
    from: '_User',
    localField: 'user',
    foreignField: 'objectId',
    as: 'userobject'
}

在MongoDB语法和解析服务器聚合管道语法之间的转换中似乎丢失了一些语法错误。

1 个答案:

答案 0 :(得分:0)

您可以编写失败的测试吗

fit('order by pointer', (done) => {
    const pointer1 = new TestObject({ value: 1});
    const pointer2 = new TestObject({ value: 2});
    const pointer3 = new TestObject({ value: 3});

    const obj1 = new TestObject({ pointer: pointer1 });
    const obj2 = new TestObject({ pointer: pointer2 });
    const obj3 = new TestObject({ pointer: pointer3 });
    const pipeline = [
      {
        project: {
          tempPointer: { $substr: [ "$_p_pointer", 11, -1 ] }, // Remove TestObject$
        }
      },
      {
        lookup: {
          from: "test_TestObject",
          localField: "tempPointer",
          foreignField: "_id",
          as: "tempPointer"
        }
      },
      {
        unwind: {
          path: "$tempPointer",
        }
      },
      { sort : { "tempPointer.value" : -1 } }
    ];
    Parse.Object.saveAll([pointer1, pointer2, pointer3, obj1, obj2, obj3]).then(() => {
      const query = new Parse.Query(TestObject);
      return query.aggregate(pipeline);
    }).then((results) => {
      expect(results.length).toEqual(3);
      expect(results[0].tempPointer.value).toEqual(3);
      expect(results[1].tempPointer.value).toEqual(2);
      expect(results[2].tempPointer.value).toEqual(1);
      console.log(results);
      done();
    }).catch((error) => {
      console.log(error);
      done();
    });
  });