Столкновение имени поля (_id) при выполнении раскрутки - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть коллекция монго, где документы выглядят так:

{ 
  _id: "384iojweiu83ur8233uui",
  name: "Jack",
  friends: [
    { 
      _id: "384798237498234",
      name: "Alfred"
    },
    { 
      _id: "384798234749829",
      name: "Deborah"
    }
  ]
}

Я хочу получить человека, которому дано _id, и только другу, поданному другу _id. Как то так:

{ 
  _id: "384iojweiu83ur8233uui",
  name: "Jack",
  friend_id: "384798237498234",
  friend_name: "Alfred"  
}

Я пытался сделать это с помощью метода unwind в драйвере c # mongo, однако я застрял на этом этапе.

var people = await collection.Aggregate()
    .Unwind<Person, PersonWithFriend>(_ => _.friends } )
    .Match( _ => _.Id == new ObjectId("5b646004b5728100042dd358"))
    .ToListAsync(); 

1 Ответ

0 голосов
/ 12 сентября 2018

Вы можете использовать позиционный оператор $, чтобы вернуть только первый соответствующий элемент массива:

db.users.find(
    { "friends._id": "384798237498234" },
    { "name": 1, "friends.$": 1 }
);

Или, если вам нужно сопоставить несколько условий в поддокументе friends, вы можете использовать $elemMatch:

db.users.find(
    { "friends":  { 
        "$elemMatch": { "id": "384798237498234",  "somethingElse": "..." }
    }},
    { "name": 1, "friends.$": 1 }
);

Который сгенерирует результат с массивом friends с одним элементом:

{ 
    _id: "384iojweiu83ur8233uui",
    name: "Jack",
    friends: [{
        id: "384798237498234",
        name: "Alfred"  
    }]
}

Если вам действительно нужно, чтобы у друга id и name были в корне объекта результата, то вы можете сделать то же самое с помощью структуры агрегации и добавить шаг разворота в конце.

В C # должно быть что-то вроде этого:

users
    .Find(user => user.friends.Any(friend => friend.id == "384798237498234"))
    .Project(projection)
    .ToListAsync();
...