0

I have the following codeblock:

var r = this.collections.competitions.Find(filter)
                                             .Project(x => x.TeamRanks)
                                             .Project(t => t.Logo)
                                             .Sort(sort)
                                             .Skip(prev)
                                             .Limit(count)
                                             .Single();

I have this Competition collection which have 3 fields

Class Competition {
           public ObjectId _Id;
           public string Logo;
           public List<string> TeamRanks
}

The filter here is on the Competition._Id. I want to get the Logo AND the first 5 ranked teams in a Rank ascending order.(Which are given by the count value) The list might be huge so I want to use Project here (or an alternative solution with Fields) but it can't seem to work. issues:

1. r is of type string which is the second Project and ignoring the TeamRanks.

2. How can I only get the top 5 ranked teams in an ascending order?

TIA.

EDIT

I just now noticed that the entire sort, skip and limit are done on the competition, I want it to be applied on the TeamRanks of course. So if, for example, the method receives count = 7 and some competitionId, the method need to return the competition with the provided id and inside it the top 7 teams ordered..

Ori Refael
  • 2,888
  • 3
  • 37
  • 68

1 Answers1

2
ObjectId _idFilter = new ObjectId();//you set your _Id filter to whatever you need
Competition _theCompetition = await __db.GetCollection<Competition>("Competiton")
    .Find(Builders<Competition>.Filter.Eq("_Id", _idFilter)).SingleAsync();
int _count = 5; //your chosen count
List<string> _orderedList = _theCompetition.TeamRanks
    .OrderBy(teamRank => teamRank).Take(_count).ToList();

EDIT
Below is the code that gets the first five elements of the TeamRanks array in the returned document

var __projection = Builders<Competition>.Projection;
var _theCompetition = await __db.GetCollection<Competition>("Competiton")
.Find(Builders<Competition>.Filter.Eq("_id", _idFilter))                  
.Project(__projection.Include(x=>x.Logo).Include(x=>x.TeamRanks).Slice("TeamRanks", 5))
.SingleAsync();
IsaacBok
  • 424
  • 5
  • 18
  • This is so wrong. Im getting the entire document here, its what i want to prevent – Ori Refael Feb 18 '16 at 21:30
  • you can sort the documents at the root level but sorting array elements when you do a find() is the challenging part. You may need to do an aggregation – IsaacBok Feb 18 '16 at 23:32
  • I dont mind sorting it when entering it. Just need the method for getting the first five – Ori Refael Feb 19 '16 at 14:34
  • just edited my answer to include code that uses projection with slice to get the first 5 elements of the array – IsaacBok Feb 19 '16 at 17:58
  • Just to add -- the order of the method chaining on the projection does matter. The slice will not work correctly unless called after the include statements. Also the slice could have been written as '.Slice(x=>x.TeamRanks, 5)' instead of using a hard coded string. – Graeme Skinner Jan 16 '17 at 15:55