Getting results from List<IMongoQuery> - c#

The code I'm working on at the moment uses the C# Mongo driver and I do lots of simple stuff like this
var query = Query.EQ("SomeBooleanField", false);
return Collection.FindAs<MyType>(query);
I have a requirement to write a query that is dynamic, i.e. the number of AND clauses varies. So I'm using something like this -
var andList = new List<IMongoQuery>();
if (whatever)
andList.Add(Query.EQ("Field1", true));
if (suchandsuch)
andList.Add(Query.EQ("Field2", false));
var query = new QueryBuilder<MyType>();
query.And(andList);
So my question is, what do I do with query in order to get some results out of it? I want a List or IEnumerable.
I can't find any useful examples online and the driver documentation isn't too helpful. Any help gratefully appreciated.

Have you tried following this format
var collection = _database.GetCollection<BsonDocument>("MyCollection");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("param1", "value1") & builder.Eq("param2", "value2");
var result = await collection.Find(filter).ToListAsync();
you are getting an error because you cannot use the FindAS<>()is this case

Related

C# Dynamic LINQ Contains using an array only evaluates the first value

Relatively new to C# and started using Dynamic LINQ to filter a data table adapter using a string. The issue I'm having is that the Where clause only seems to evaluate the first value in the string and none of the others. Here is the code I am using.
string[] ids = new string[] { "12345", "67891", "45878" };
var resultQ = (from pr in table1 select pr).AsQueryable();
var iq = resultQ.Where("#0.Contains(FieldName)", ids);
It works but only for the first value "12345" so the output of iq displays all fields for "12345". I tried using linq.dynamic.core to see if that would help but the still same result (or I haven't used it properly). I know I'm probably missing something minor here but any help would be greatly appreciated.
Also on a separate note: I wanted to convert the end result of iq which is a IQueryable type to EnumerationRowCollection type. Is this possible?
Thanks in advance
Managed to fix both points now. Either set string[] to string for dynamic LINQ to get all values in list as coded below
string ids = "12345,67891,45878";
var resultQ = (from pr in table1 select pr).AsQueryable();
var iq = resultQ.Where("#0.Contains(FieldName)", ids);
or use Syed's suggestion and change the LINQ query and keep the array (thanks again Seyed)
For the conversion of IQueryable type to EnumerationRowCollection I changed EnumerationRowCollection to IEnumerable and this worked for all my LINQ queries
Thanks
Just use this. It will works fine.
string[] ids = new string[] { "12345", "67891", "45878" };
var resultQ = (from pr in table1 select pr).AsQueryable();
var iq = resultQ.Where(w => ids.Contains(w.Id)).ToList();

Trying to user mongodb's filter.near

I'm trying to find the nearest cordinations from a nested mongodb document. The error I keep getting is the following:
I've tried everything I could think of. I tried to add index 2d, that didn't work neither.
var point = GeoJson.Point(GeoJson.Geographic(38.8086, -85.1792));
var locationQuery = new FilterDefinitionBuilder<Book>().NearSphere(tag => tag.CitiesInBook[-1].Location, point,
5000);
var query = collection.Find(locationQuery).Limit(10);
var a = query.ToList();
Planner returned error
unable to find index for $geoNear query.'

How to fetch data from MongoDB collection in C# using Regular Expression?

I am using MongoDB.Drivers nuget package in my MVC (C#) web application to communication with MongoDB database. Now, I want to fetch data based on specific column and it's value. I used below code to fetch data.
var findValue = "John";
var clientTest1 = new MongoClient("mongodb://localhost:XXXXX");
var dbTest1 = clientTest1.GetDatabase("Temp_DB");
var empCollection = dbTest1.GetCollection<Employee>("Employee");
var builder1 = Builders<Employee>.Filter;
var filter1 = builder1.Empty;
var regexFilter = new BsonRegularExpression(findValue, "i");
filter1 = filter1 & builder1.Regex(x => x.FirstName, regexFilter);
filter1 = filter1 & builder1.Eq(x => x.IsDeleted,false);
var collectionObj = await empCollection.FindAsync(filter1);
var dorObj = collectionObj.FirstOrDefault();
But, the above code is performing like query.
It means it is working as (select * from Employee where FirstName like '%John%') I don't want this. I want to fetch only those data whose FirstName value should match exact. (like in this case FirstName should equal John).
How can I perform this, can anyone provide me suggestions on this.
Note: I used new BsonRegularExpression(findValue, "i") to make search case-insensitive.
Any help would be highly appreciated.
Thanks
I would recommend storing a normalized version of your data, and index/search upon that. It will likely be considerably faster than using regex. Sure, you'll eat up a little more storage space by including "john" alongside "John", but your data access will be faster since you would just be able to use a standard $eq query.
If you insist on regex, I recommend using ^ (start of line) and $ (end of line) around your search term. Remember though, that you should escape your find value so that its contents isn't treated as RegEx.
This should work:
string escapedFindValue = System.Text.RegularExpressions.Regex.Escape(findValue);
new BsonRegularExpression(string.Format("^{0}$", escapedFindValue), "i");
Or if you're using a newer framework version, you can use string interpolation:
string escapedFindValue = System.Text.RegularExpressions.Regex.Escape(findValue);
new BsonRegularExpression($"^{escapedFindValue}$", "i");

is filter is replaceable of query in mongo queries using c#?

I'm new to mongo in c#
I found tow ways to find documents based on search critiria:
the first using filter:
var collection = _database.GetCollection<BsonDocument>("restaurants");
var filter = Builders<BsonDocument>.Filter.Eq("address.zipcode", "10075");
var result = await collection.Find(filter).ToListAsync();
The second using query:
MongoCollection<BsonDocument> books;
var query = Query.EQ("author", "Kurt Vonnegut");
foreach (BsonDocument book in books.Find(query)) {
// do something with book
}
What's the best way to find documents based to what MongoDB recommendation?
As far I know query builders (like your second example using Query.EQ) belong to old versions of C# drivers (1.X) (see Query class). Also I suggest you to see Builder section in this link that confirm query builders is the old way to consult data.
After the release of the 2.0 version of the .NET driver, a lot of changes were made, including the way of consult the data (you can read more about that in this link). If you are using the last C# driver version you should use your first approach.
The first way you mentioned is quite fine. You might want to incorporate using a mongo cursor as well to allow you to iterate through results
var collection = _database.GetCollection<BsonDocument>("restaurants");
var filter = Builders<BsonDocument>.Filter.Eq("address.zipcode", "10075");
using(var _cursor = await collection.Find(filter).ToCursorAsync())
{
while(await _cursor.MoveNextAsync())
{
foreach(var _document in _cursor.Current) //gets current document
{
//you can do things like get the _id of the document
var _id = _document["_id"];
}
}
}

allowDiskUse in Aggregation Framework with MongoDB C# Driver

I would like to allowDiskUse:true. However I could not found any example which explain allowDiskUse enabling for MongoDB C# driver.
How can I enable allowDiskUse in MongoDB C# driver?
My sample code like that
var pipeline = new[] { match, project, group, limit, sort, allow };
List<SMBMostInfluentialUser> result = db
.GetCollection<SMBTwitterStatus>("TwitterStatus")
.Aggregate(pipeline).ResultDocuments.Select(x =>
new User
{
Influence = Convert.ToDouble(x["Influence"]),
User = new SMBUser((BsonDocument)x["User"])
}).ToList();
Use the other overload of Aggregate that takes an AggregateArgs parameter and gives you more control over the operation, including setting AllowDiskUse:
var pipeline = new BsonDocument[0]; // replace with a real pipeline
var aggregateArgs = new AggregateArgs { AllowDiskUse = true, Pipeline = pipeline };
var aggregateResult = collection.Aggregate(aggregateArgs);
var users = aggregateResult.Select(x =>
new User
{
Influence = x["Influence"].ToDouble(),
User = new SMBUser(x["user"].AsBsonDocument)
}).ToList();
Note that the return type of this overload of Aggregate is IEnumerable<BsonDocument> so you no longer have to use the ResultDocuments property.
Just to be clear, the Select is being executed client side. You might be able to arrange it so that the documents coming out of your aggregation pipeline can be directly deserialized into instances of one of your classes.
For more recent versions of MongoDB C# driver (not sure starting with what version), the syntax is:
var aggregateOptions = new AggregateOptions{ AllowDiskUse = true};
var aggregateResult = collection.Aggregate(aggregateOptions);

Categories

Resources