Thomas
Thomas

Reputation: 12107

MongoDB C# Get all documents from a list of IDs

I have a list of Ids

List<string> Ids;

and I would like to retrieve all the documents matching these Ids.

There are solutions on the web:

var ids = new int[] {1, 2, 3, 4, 5};
var query = Query.In("name", BsonArray.Create(ids));
var items = collection.Find(query);

but they're all with the old C# driver and with the (not so new anymore) 2.2.4 driver the API has changed and I can't find how to build this query.

Upvotes: 14

Views: 25316

Answers (4)

yBother
yBother

Reputation: 718

with latest c# mongo driver you also can leverage LINQ support:

var results = this.mongoClient.GetCollection<Employee>()
                              .AsQueryable()
                              .Where(x => idList.Contains(x.Id))
                              .ToList();

Upvotes: 0

Rokit
Rokit

Reputation: 1141

This looks to be the current equivalent of what you were attempting:

var ids = new int[] {1, 2, 3, 4, 5};
var filter = Builders<BsonDocument>.Filter.In("name", ids);
var items = collection.Find(filter);

Upvotes: 3

itstudes
itstudes

Reputation: 421

I struggled with this recently.

Using the new driver (v2.14.X) this can be achieved with the $in operator. This Mongo link describes the $in functionality reasonably well.

You can either apply the LINQ format:

var ids = new List<string> {"id1", "id2", "etc"};
someMongoCollection.Find(o => o.Any(i => ids.Contains(o.Id));

The LINQ format works well except for cases where you're trying to chain queries together (i.e. if you are querying with optional data, so int[] ages, string[] ids, etc.). In that case you effectively want to build up the query as necessary.

For that application I use the native mongo format (also described in the Mongo link above).

{ Id: { $in: ["id1", "id2", "etc"] } }

This is passed as a string to create a BsonDocument which is then used as the filter on the .Find() operation. You can add more filters as necessary. More information on passing in data to create BsonDocument objects can be found at this link.

See example code snip below:

// 1 - init base filter (this fetches everything)
var filter = new BsonDocument();  

// 2 - init id data
var ids = new List<string> {"id1", "id2", "etc"};
var idsString = ids.ConvertAll(i => $"\"{i}\"");

// 3 - create the mongo formatted query and generate the BsonDocument
var bsonToParse = $"{{ \"Id\": {{ $in: [{string.Join(",", idsString )}] }} }}";
var idsFilterBson = BsonDocument.Parse(bsonToParse);

// 4 - add the BsonDocument to the already existing filter
filter.Add(idsFilterBson);

// perform steps 2-4 for any other optional query data

// run the final find operation
var dataFromDb = await someMongoCollection.Find(filter).Limit(limit).ToListAsync();

Upvotes: 0

profesor79
profesor79

Reputation: 9473

please see snippet below (made using LINQPad)

void Main()
{
    // To directly connect to a single MongoDB server
    // or use a connection string
    var client = new MongoClient("mongodb://localhost:27017");
    var database = client.GetDatabase("test");


var collectionEmpInfo = database.GetCollection<Employee>("Employee");
Employee EmpInfo = new Employee
{

    EmpID = "103",
    EmpName = "John",
    CreatedAt = DateTime.Now,
    EmpMobile = new List<Mobile>
    {
        new Mobile{ MobNumber = "55566610", IsPreferred = true, MobID = ObjectId.GenerateNewId() },
        new Mobile{ MobNumber = "55566611", IsPreferred = false, MobID = ObjectId.GenerateNewId() },
    }
};
//collectionEmpInfo.InsertOne(EmpInfo);

var filterDef = new FilterDefinitionBuilder<Employee>();
var filter = filterDef.In(x=>x.EmpID , new[]{"101","102"});
filter.Dump();
var empList = collectionEmpInfo.Find(filter).ToList();
empList.Dump();
}
public class Employee
{
   public ObjectId Id  { get; set; }
    public string EmpID { get; set; }
    public string EmpName { get; set; }
    public List<Mobile> EmpMobile { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class Mobile
{
    public ObjectId MobID { get; set; }
    public string MobNumber { get; set; }
    public bool IsPreferred { get; set; }
}

and results screenshot

linquPaDscreenShot

Upvotes: 18

Related Questions