Получить документ только с поддокументами, соответствующими критериям с помощью мангуста

У меня есть эта модель мангуста:

var mySubEntitySchema = new Schema({
  property1: String,
  property2: String
});

var myEntitySchema = new Schema({
  name: String,
  sub: [mySubEntitySchema]
});

export var MyEntityModel: mongoose.Model<MyEntityDocument> = mongoose.model<MyEntityDocument>("MyEntity", myEntitySchema);

Теперь я хочу получить конкретный MyEntityDocument, для которого у меня есть _id, но только с вложенными документами, соответствующими property1 = "example".

Есть ли способ сделать это?

Я попробовал решение с помощью Aggregate, но безуспешно:

MyEntityModel.aggregate([
{$match: { "_id": myId, "sub.property1":"example" }},
      {$unwind: "$sub"},
      {$match: { "sub.property1":"example"}},
      {$group: {"_id":"$_id","subs":{$push:"$sub"}}}
    ], (error, result) => {
        console.log("Result = " + JSON.stringify(result));
      }
    });

Но ничего не возвращает. Если я не поставлю "_id": myId в первое предложение $match, то я получу результаты, но мне нужен только один результат, соответствующий имеющемуся у меня _id.

Кто-нибудь знает, как я могу это сделать?

РЕДАКТИРОВАТЬ: Как и просили, вот пример.

С этими данными:

  {
    "_id": "54c12276fcb2488d300795e4",
    "name": "a",
    "sub": [
      {
        "_id": "54c12276fcb2488d300795e0",
        "property1": "example",
        "property2": "something"
      },
      {
        "_id": "54c12276fcb2488d300795e1",
        "property1": "notmuch",
        "property2": "somethingelse"
      },
      {
        "_id": "54c12276fcb2488d300795e2",
        "property1": "notinteresting",
        "property2": "something"
      },
      {
        "_id": "54c12276fcb2488d300795e3",
        "property1": "example",
        "property2": "anotherthing"
      }
    ]
  },
  {
    "_id": "54c12277fcb2488d300795e5",
    "name": "b",
    "sub": [
      {
        "_id": "54c12276fcb2488d300795e6",
        "property1": "example",
        "property2": "word"
      }
    ]
  }

Мне нужен объект с _id "54c12276fcb2488d300795e4" и поддокументы, соответствующие property1 = "example". Итак, ожидаемый результат:

  {
    "_id": "54c12276fcb2488d300795e4",
    "name": "a",
    "sub": [
      {
        "_id": "54c12276fcb2488d300795e0",
        "property1": "example",
        "property2": "something"
      },
      {
        "_id": "54c12276fcb2488d300795e3",
        "property1": "example",
        "property2": "anotherthing"
      }
    ]
  }

person Camille Blanc    schedule 21.09.2016    source источник
comment
Можете ли вы добавить пример набора данных и результат, который вы хотите здесь ??   -  person Ananth Pai    schedule 21.09.2016
comment
@AnanthPai Только что отредактировано, чтобы добавить образцы данных и ожидаемый результат.   -  person Camille Blanc    schedule 21.09.2016


Ответы (2)


Вы можете использовать findOne для получения того, что хотите.

MyEntityModel.findOne({_id : myId , "sub.property1" :"example"},{'sub.$' : 1},function(err,result){
    if(!err)
    {
        if(result)
        {
            //result is the document you were searching for
        }
    }
});

{'sub.$' : 1} вернет только соответствующий элемент.

Ознакомьтесь с документацией по запросам mongoose для лучшего понимания.

person Ravi Shankar Bharti    schedule 22.09.2016

Ваш запрос, похоже, работает нормально и, как и ожидалось, дает результат, за исключением того, что синтаксис агрегатной функции неверен. Перейдите по этой ссылке, чтобы узнать, как пишутся агрегированные запросы с помощью mongoose. Вы не должны передавать массив, как в mongodb console. Просто передайте запросы, разделенные запятыми, как показано в запросе ниже.

MyEntityModel.aggregate(
  {$match: { "_id": myId, "sub.property1":"example" }},
  {$unwind: "$sub"},
  {$match: { "sub.property1":"example"}},
  {$group: {"_id":"$_id","name": {"$first": "$name"}, "subs":{$push:"$sub"}}}
, (error, result) => {
    console.log("Result = " + JSON.stringify(result));
  }
});
person Ananth Pai    schedule 22.09.2016
comment
Все еще не работает для меня, я понятия не имею, почему. Если я не помещаю совпадение в _id, оно просто работает нормально, но как только я добавляю этот критерий, результат пуст. Ну, в моем реальном коде я точно не совпадаю по _id, но по другому свойству, не знаю, меняет ли это вещи? - person Camille Blanc; 22.09.2016
comment
можете ли вы поделиться значением myId до его передачи в агрегатную функцию в console.log - person Ananth Pai; 23.09.2016
comment
Я упростил свой код, чтобы его было легче понять, поэтому на самом деле у меня нет значения myId. Но в любом случае мои критерии хороши, потому что дела обстоят так: findOne с _id: myId возвращает результат. Агрегат без _id: myId возвращает все документы с поддокументами, соответствующими sub.property1: example (и только эти поддокументы). Как только я добавляю _id: myId к агрегату, я внезапно не получаю результата. - person Camille Blanc; 24.09.2016