2016-01-18 2 views
2

У меня есть документ GradePovider, содержащие элементы:Mongoose найти все поддокументы, удовлетворяющих условию

{ 
"_id": ObjectId("568a466f2c48409006ab4862"), 
"values": [ 
    { 
     "_id": ObjectId("568a466f2c48409006ab4868"), 
     "description": "has et delicata moderatius" 
    }, 
    { 

     "_id": ObjectId("568a466f2c48409006ab4867"), 
     "description": "description two" 
    }, 
    { 

     "_id": ObjectId("fakeId"), 
     "description": "description three" 
    } 
    ] 
} 

И я хотел бы сделать поиск по списку value._id. так, что я получаю в ответ на поиск по [ObjectId ("568a466f2c48409006ab4868"), ObjectId ("568a466f2c48409006ab4867")]:

{ 
"_id": ObjectId("568a466f2c48409006ab4862"), 
"values": [ 
    { 
     "_id": ObjectId("568a466f2c48409006ab4868"), 
     "description": "has et delicata moderatius" 
    }, 
    { 

     "_id": ObjectId("568a466f2c48409006ab4867"), 
     "description": "description two" 
    } 
    ] 
} 

Я попытался с помощью этого кода:

gradeModel.GradeProvider.find({ 
     'values._id': { 
      $in: node.grades 
     } 
     }, { 
     "values.$": true 
     }, function (err, gradeProviders) {} 

Этот код возвращает только первое совпадение значений для каждого классаProvider. Я думаю, мне нужно будет использовать агрегацию этого. Пока я не понял.

radeModel.GradeProvider.aggregate([{ 
     $match: { 
      'values._id': { 
      $in: node.grades 
      } 
     } 
     }, { 
     $project: { 
      providerName: 1, 
      values: 1 
     } 
     }], function (err, gradeProviders) {} 

Этот код возвращает право GradesProviders, но возвращает все значения.

Спасибо!

ответ

1

Следующая трубопровод должен работать для вас:

var pipeline = [ 
    { 
     "$match": { 
      "values._id": { "$in": node.grades } 
     } 
    }, 
    { 
     "$project": { 
      "providerName": 1,    
      "values": { 
       "$setDifference": [ 
        { 
         "$map": { 
          "input": "$values", 
          "as": "el", 
          "in": { 
           "$cond": [ 
            { 
             "$setIsSubset": [ 
              [ "$$el._id" ], 
              node.grades 
             ] 
            }, 
            "$$el", 
            false 
           ] 
          } 
         } 
        }, 
        [false] 
       ] 
      } 
     } 
    } 
]; 

gradeModel.GradeProvider.aggregate(pipeline, function (err, gradeProviders) {}); 

Операторы, которые составляют существенную разницу являются $setDifference и $map операторы. Оператор по существу создает новое поле массива, которое содержит значения в результате оцениваемой логики в подвыражении для каждого элемента массива. Оператор $setDifference возвращает набор с элементами, которые отображаются в первом наборе, но не во втором наборе; т.е. выполняет относительное дополнение второго набора относительно первого. В этом случае он будет возвращать конечный values массив, который содержит элементы, не связанные с родительскими документами через _id собственности, на основе условного оператора $cond, который вычисляет выражение, возвращаемое оператором $setIsSubset.

+0

Благодарим вас за ответ. –

+0

@marouaneRaji Это решило ваш вопрос? – chridam

+0

Да, у меня есть только один момент "$ setIsSubset": [ [ "$$ el._id"], node.grades ] не возвращает верно для двух идентичных ObjectId (но не тот же экземпляр). Любая идея, как управлять этим случаем? кроме применения toString в массиве ObjectId? –

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