2016-11-14 3 views
2

У меня есть коллекция группа, как это:Сравнивая поле такого элемента в массиве с полем в MongoDB

{ 
    "_id" : ObjectId("5822dd5cb6a69ca404e0d93c"), 
    "name" : "GROUP 1", 
    "member": [ 
     { 
      "_id": ObjectId("5822dd5cb6a69ca404e0d93d") 
      "user": ObjectId("573ac820eb3ed3ea156905f6"), 
      "task": ObjectId("5822ddecb6a69ca404e0d942"), 
     }, 
     { 
      "_id": ObjectId("5822dd5cb6a69ca404e0d93f") 
      "user": ObjectId("57762fce5ece6a5d04457bf9"), 
      "task": ObjectId("5822ddecb6a69ca404e0d943"), 
     } 
    ], 
    curTask: { 
     "_id": ObjectId("5822ddecb6a69ca404e0d942"), 
     "time": ISODate("2016-01-01T01:01:01.000Z") 
    } 
} 
{ 
    "_id" : ObjectId("573d5ff8d1b7b3b32e165599"), 
    "name" : "GROUP 2", 
    "member": [ 
     { 
      "_id": ObjectId("574802e031e70b503eabe195") 
      "user": ObjectId("573ac820eb3ed3ea156905f6"), 
      "task": ObjectId("5775f1a74b41037e246a51d1"), 
     }, 
     { 
      "_id": ObjectId("574802e031e70b503eabe198") 
      "user": ObjectId("573ac79beb3ed3ea156905f4"), 
      "task": ObjectId("576cfa042c0a4054794dd242"), 
     } 
    ], 
    curTask: { 
     "_id": ObjectId("577249a2f9dba0c750ef705b"), 
     "time": ISODate("2016-01-01T01:01:01.000Z") 
    } 
} 
{ 
    "_id" : ObjectId("574802e031e70b503eabe194"), 
    "name" : "GROUP 3", 
    "member": [ 
     { 
      "_id": ObjectId("574be0a2bf16234f5a752f83") 
      "user": ObjectId("573ac79beb3ed3ea156905f4"), 
      "task": ObjectId("5822ddecb6a69ca404e0d942"), 
     }, 
     { 
      "_id": ObjectId("574d397d6e9f07d64d1e4e40") 
      "user": ObjectId("57762fce5ece6a5d04457bf9"), 
      "task": ObjectId("5822ddecb6a69ca404e0d943"), 
     } 
    ], 
    curTask: { 
     "_id": ObjectId("5822ddecb6a69ca404e0d942"), 
     "time": ISODate("2016-01-01T01:01:01.000Z") 
    } 
} 

И я хочу, чтобы быть в состоянии найти всю группу, в которой пользователь с ObjectId 573ac820eb3ed3ea156905f6 (1 пользователя в 1-е группы) не выполняют ту же задачу, что и currentTask. До сих пор я написал этот вопрос:

db.getCollection('groups').find({"member":{ "$elemMatch": {"user": ObjectId("573ac820eb3ed3ea156905f6") 
, "task": { "$ne":"this.curTask._id"}}}}) 

Но это, похоже, не работает, как она по-прежнему возвращает группу, где пользователь 573ac820eb3ed3ea156905f6 имеющий свою task === curTask._id. Первая половина elemMatch, похоже, работает нормально (только найдите группу с пользователем с objectid 573ac820eb3ed3ea156905f6 в члене, запрос возвращает только группу 1 и 2, так как группа 3 не имеет этого пользователя.), Но я не могу заставить mongodb сравнить поле в объекте массива с другим полем документа. Кто-нибудь знает, как мне сделать это сравнение?

+0

сообщение данных дампа –

+0

Не получать подсказки о том, как мы можем использовать этот элемент внутри согласовани –

+0

ли вы заботитесь о задачах других членов массива, который соответствовал 1-ое состояние. – hyades

ответ

1

Есть два пути решения этой проблемы -

Первый - с помощью $where. Используя $where, вы можете использовать код Javascript внутри запросов mongodb. Делает код гибким, но недостатком является то, что он работает медленно, так как Javascript-код должен работать, а не более оптимизирован код MongoDB C++.

db.getCollection('groups').find({ 
    $where: function() { 
      var flag = 0; 

      for(var i=0; i<obj.member.length;i++) { 
        if(obj.member[i].user.str == ObjectId("573ac820eb3ed3ea156905f6").str && obj.member[i].task.str != obj.curTask._id.str){flag = 1; break;} 
       } 
      return flag; 
     } 
    }) 

Второй - Использование конвейера агрегации. Здесь я разматываю массив, выполняя матчи, как описано, и, наконец, воссоздавая массив по мере необходимости. Если несоответствующие элементы в массиве member не нужны, можно опустить последнюю группу группировки.

[ 
{$match: {'member.user': ObjectId("573ac820eb3ed3ea156905f6")}}, 
{$unwind: '$member'}, 
{$project: { 
    name: 1, 
    member: 1, 
    curTask: 1, 
    ne: {$and: [{$ne: ['$member.task', '$curTask._id']}, {$eq: ['$member.user', ObjectId("573ac820eb3ed3ea156905f6")]}]} 
    }}, 
{$group: { 
    _id: '$_id', 
    member: {$push: '$member'}, 
    curTask: {$first: '$curTask'}, 
    name: {$first: '$name'}, 
    check: {$sum: {$cond: ['$ne', 1, 0]}} 
    }}, 
{$match: {check: {$gt: 0}}} 
] 
+0

Большое вам спасибо за ответ. Я даже не знал, что вы можете использовать js-код в запросе. 1-й способ отлично работает для меня (мне просто нужно изменить '.str' на' + '' ', чтобы он также охватывал случай, когда у пользователя нет какой-либо задачи, назначенной ему, но его задача -« null »). – Megazero

Смежные вопросы