C# MongoDB .NET Driver DateDiff Two Date Fields In Document - c#

I need to query a MongoDB Collection where the date difference between two date fields, within each Document, is equal to 1 day.
I've tried using the MongoDB.Driver.Builders using the Where or Eq FilterDefinitions but cannot get it to work. Is there a way to do this? If so, is there a way to exclude the time portion so I'm just getting the difference between two dates?
Here is the code I have:
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("local");
var collection = database.GetCollection<BsonDocument>("testCollection");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Exists("{$cond:[{$gte:[{$divide:[{$subtract:[DateField1,DateField2]},1000*60*60*24]},1]}]}");
var documents = collection.Find(filter).ToList();

Related

Issue deserializing a date represented as a string in document from Cosmos DB

I currently have a C# application that queries Cosmos DB. In the database everything is stored as strings. When I query the container for the document and pull out the information it looks like the deserialization process is treating it like a date and its applying the Date Time Offset. Strange part is this process of querying the DB never converts it to a date? I would like it to just pass through the app as its stored in Cosmos.
Here is the document shape in Cosmos:
{
"id": "uniqueId",
"MyDate" : "2021-07-24T23:59:00+0000"
}
Here is the code that connects to CosmosDB
using(var client = new CosmosClient("EndPoint","Key")
{
string sqlQueryText = "Select * From c Where .... ";
QueryDefinition querySQL = new QueryDefination(sqlQueryText);
var container = client.GetContainer("databaseId", "ContainerId");
var iii = container.GetItemQueryIterator<Document>(querySQL);
var myList = new List<Document>();
while(iii.HasMoreResults)
{
FeedResponse<Document> currentRS = iii.ReadNextAsync().Result;
foreach(Document doc in currentRS)
{
myList.Add(doc);
}
}
}
Here is the Output of the this process in C#, By output I mean if you look at the myList Object and inspect the Mydate Property you will see this string below.
"07/24/2021 19:59:00"
which is the date & time with the date time offset.
How do I prevent this?
This application should just pass the string straight through with no regard for "Real Type".
I would just like to get "2021-07-24T23:59:00+0000"

I want to copy documents from one collection to another

I have 2 collections in my database. Let's say collection_1 and collection_2. I want to copy or move all of my documents in collection_1 to collection_2 using C#.
Any idea please?
Here's a solution to copy between databases. If they are on the same database then it is even more simple, just use one mongo client
var fromConnectionString = "mongodb://localhost:27017"; // if copy between same database then obviously you only need one connectionstring and one MongoClient
var toConnectionString = "mongodb://localhost:27017";
var sourceClient = new MongoClient(fromConnectionString);
var copyFromDb = sourceClient.GetDatabase("CopyFromDatabaseName");
var copyCollection = copyFromDb.GetCollection<BsonDocument>("FromCollectionName").AsQueryable(); // or use the c# class in the collection
var targetClient = new MongoClient(toConnectionString);
var targetMongoDb = targetClient.GetDatabase("CopyToDatabase");
var targetCollection = targetMongoDb.GetCollection<BsonDocument>("ToCollectionName");
targetCollection.InsertMany(copyCollection);
With database query.
Source :https://docs.mongodb.com/manual/reference/method/db.cloneCollection/
db.cloneCollection('mongodb.example.net:27017', 'profiles', { 'active' : true } )
With C#
Source: Duplicate a mongodb collection
var source = db.GetCollection("test");
var dest = db.GetCollection("testcopy");
dest.InsertBatch(source.FindAll());

MongoDB query to C# equivalent ObjectID subset

So I have done as much research as sanely possible and could not come to a conclusion that worked for me. I have a query I use in Mongo to only grab _id's that end with a certain character. These are standard base 16 object ids in MongoDB. What I want from this is to divide up work where the one doing the query is only working on Ids that end in the base 16 value. So I would have 16 processes responsible for running their respective instructions against ObjectId where _id ends with 0-e.
db.Collection.find({ $where : "this._id.toString().match(/(SomeNumber)..$/i)"})
My question is what would be the C# driver equivalent of this I could use with other filters such as Builders.Filter.Lte("Somefield", someVal) and then .FindOne()?
My final would look something like
var filter1 = Builders<BsonDocument>.Filter.Where(Id matches regex);
var filter2 = Builders<BsonDocument>.Filter.Lte("Somefield", someVal);
var qfilter = filter1 & filter2;
var returndoc = Collection.FindOne(qfilter);
In hopes that this will return one document at a time where the last value of my object id matches the one I am interested in and also has Somefield less than someVal.
This is what I have tried thus far.
//This one doesn't work because objectId does not support regex comparison
var iDFilter = Builders<BsonDocument>.Filter.Regex("_id", _threadIndexB16);
//These two never returned any values
var iDFilter = Builders<BsonDocument>.Filter.Where("this._id.toString().match(/\"" + _myWantedIndex + "..$/i)\")";
var iDFilter = new BsonDocument("$where", "this._id.toString().match(/" + _myWantedIndex + "..$/i)");
Help converting this would be appreciated. Alternatives are also welcome as long as the result is the document I am after.

How to read a Mongo Document and save it to an object?

I need to read certain fields in documents from Mongo. I filtered out a document using the Filter.EQ() method but how can I find and store a field in that document? This is my code:
public void human_radioButton_Checked(object sender, RoutedEventArgs e)
{
Upload human = new Upload(); //opens connection to the database and collection
var filter = Builders<BsonDocument>.Filter.Eq("name", "Human");
race_desc description = new race_desc();
description.desc = Convert.ToString(filter);
desc_textBox.Text = description.desc;
However, this doesn't work since I didn't grab any fields, just the document. So how can I read a field called 'A' and store it into an object?
Thanks
When you define a filter using the Builders<BsonDocument>.Filter here, you merely define a filter that you can use/execute in a query. Much like storing a SQL string in a string variable.
What you missed here is executing the filter and actually retrieve the data. According to Mongodb C# driver doc:
var collection = _database.GetCollection<BsonDocument>("restaurants");
var filter = Builders<BsonDocument>.Filter.Eq("borough", "Manhattan");
var result = await collection.Find(filter).ToListAsync();
Then you can iterate the results and access the properties like
foreach(var result in results)
{
//do something here with result.your_property
}
And if you just want the first of the result
var result = (await collection.Find(filter).ToListAsync()).FirstOrDefault();
Now if you want to cast the BsonDocument you got now to your own class deserialize document using BsonSerializer:
var myObj = BsonSerializer.Deserialize<YourType>(result);
You can also map it to your own class:
var yourClass = new YourType();
yourClass.Stuff= result["Stuff"].ToString();

Deleting documents in a batch by expiration date in ravenDB

I am trying to delete documents older than a certain point in ravenDB. I am still unfamiliar with Lucene and am having a hard time constructing this query.
_Session.Advanced.DatabaseCommands.DeleteByIndex(
typeof(AssetsByExpirationDate).Name,
new IndexQuery()
{
Query = string.Format("ExpirationDate:[\"{0:MM/dd/yyyy}\" TO \"{1:MM/dd/yyyy}\"]", DateTime.MinValue, new DateTime(2012,6,1))
});
What is the correct syntax for the Query to delete items before a certain date?
You can build your query outside the DatabaseCommands IndexQuery and use Query.ToString() to populate the IndexQuery Query string as below :
var query = session.Advanced.LuceneQuery<Asset, AssetsByExpirationDate>()
.WhereBetween("ExpirationDate",DateTime.MinValue,new DateTime(2012, 6, 1));
var queryString = query.ToString();
session.Advanced.DatabaseCommands.DeleteByIndex(typeof(AssetsByExpirationDate).Name, new IndexQuery
{
Query = queryString
});
Using this way and if you are not very familiar with lucene query syntax, RavenDb Query API build it for you as shown before by calling .ToString() and got the following Lucene formatted query string.
ExpirationDate:{00010101000000000 TO 20120601000000000}
Note that deleting using DatabaseCommands does't work with stale indexes. So be careful or use a standard lucene query to retrieve documents to delete and then perform a simple Session.Delete(asset) foreach documents to delete.
var query = session.Advanced.LuceneQuery<Asset, AssetsByExpirationDate>()
.WhereBetween("ExpirationDate",DateTime.MinValue,new DateTime(2012, 6, 1));
var assets = query.ToList();
foreach(var asset in assets)
{
session.Delete<Asset>(asset);
}
session.SaveChanges();
Pay attention to pagination, since Ravendb returns only 128 results by default.

Categories