Amit Kumar Jain
Amit Kumar Jain

Reputation: 487

MongoDB: Querying for a referenced document

I am new to MongoDB and I read the MongoDB documentation. I have following structure: -

public class User
{
    [BsonId]
    public long UserId { get; set; }        
    public string LoginId { get; set; }
    public string Password { get; set; }        
    public List<string> Gateways { get; set; }
}
public class Gateway
{
    [BsonId]
    public string MACAddress { get; set; }
    public string SerialNumber { get; set; }
    public List<Device> Devices { get; set; }
}

I referenced Gateway MAC Addresses in the USER document as Gateway is also having separate existence in absence of USER. For getting all the gateways for a given UserId I am writing queries as follows: -

var userQuery = Query<User>.EQ(u => u.UserId, aUserId);
var userCursor = mMongoUserCollection.Find(userQuery);
var gateways = mMongoGatewayCollection.AsQueryable<Gateway>().Where(g => userCursor.FirstOrDefault().Gateways.Contains(g.MACAddress));

But I am getting an Exception that

"Unable to determine Serialization Information for the expression: Enumerable.FirstOrDefault<User>"

But when I write my query as follows all goes well

var userQuery = Query<User>.EQ(u => u.UserId, aUserId);
var userCursor = mMongoUserCollection.Find(userQuery);

List<string> desiredGateways = userCursor.FirstOrDefault().Gateways;
var gateways = mMongoGatewayCollection.AsQueryable<Gateway>().Where(g => desiredGateways.Contains(g.MACAddress));

I just want to know the difference between the above two.

Upvotes: 1

Views: 305

Answers (1)

i3arnon
i3arnon

Reputation: 116676

The difference is that the MongoDB C# driver can't translate the first snippet into a MongoDB query, while it can the second one.

When you call Where on an IQueryable it stores all the lambda expressions until you materialize the query be using foreach or ToList. At that stage the provider (the driver) tries to generate relevant queries to be performed in the database.

The database can't use userCursor.FirstOrDefault() as it doesn't know what FirstOfDefault is and it can't receive a cursor. It can however serialize a User instance that you have retrieved from the database previously.

Upvotes: 1

Related Questions