Find in subdocument MongoDb - c#

I need to first find the document by _id.
Then in the document to find subdocument which have a Time field is greater than the parameter lastTime
var filter = builder.Eq("_id", symbol) & builder.Gt("Update.Time", lastTime);
var result = await MongoDb.CollectionName.Find(filter).ToListAsync();
This example has a result of 0.
How to write this query? I need get this subdocument "Update" or last 3 sub-subdocument
The document has the following structure
{
{"_id", symbol},
{"Update", [
{"_id", number}, {"Time", sometime}, {"Version", versionNumber},
{"_id", number}, {"Time", sometime}, {"Version", versionNumber},
{"_id", number}, {"Time", sometime}, {"Version", versionNumber},
{"_id", number}, {"Time", sometime}, {"Version", versionNumber},}
]
}

If mongodb console will work an example:
> db.doc.save({
"_id":"123",
"update":[
{"_id":'1', "time":'345', "Version":'3'},
{"_id":'2', "time":'234', "Version":'4'}
]
})
> db.doc.findOne( { _id:"123", "update.time":{ $gt: 344 } } )
Then for C# Will can you to try ?
var collection = _database.GetCollection<BsonDocument>("name");
var filter = Builders<BsonDocument>.Filter.Gt("update.time", 344);
var result = await collection.Find(filter).ToListAsync();
This example
UPD This can be:
var collection = _database.GetCollection<BsonDocument>("name");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("_id", id) & builder.Gt("update.time", 344);
var result = await collection.Find(filter).ToListAsync();

Try using lambda expressions:
var lastTime = 1;
var result = collection.Find(x => x.Update.Contains(lastTime));

Related

Querying assets with filter returns too small subset of assets

I'm querying assets that have empty alternateId, but using the following code I only get around 7k assets. If I query without the filter and count the number of returned assets with empty alternateId, it is around 36k. It's not related to paging as I'm using the same NextPageLink paging logic in both test cases.
What could be the reason for this? I'm looking into optimizing the code by not having to get all 72k assets but only the ones with empty alternateId, and update that after having processed the asset.
I use Microsoft.Azure.Management.Media v6.0.0.
var assets = await client.Assets.ListAsync(
config.ResourceGroup,
config.AccountName,
new Microsoft.Rest.Azure.OData.ODataQuery<Asset>() {
Filter = "properties/alternateId eq ''"
}
);
You need to filter by properties/alternateId eq null to get null values. If you want both null and empty values you can use properties/alternateId eq '' or properties/alternateId eq null
Here is some sample code to test out the behavior. I added an additional filter on created date to exclude old data.
var alternateNull = await Client.Assets.CreateOrUpdateAsync(ResourceGroup, MediaAccount, "alternate_null", new Asset());
var alternateEmpty = await Client.Assets.CreateOrUpdateAsync(ResourceGroup, MediaAccount, "alternate_empty", new Asset { AlternateId = "" });
var alternateSet = await Client.Assets.CreateOrUpdateAsync(ResourceGroup, MediaAccount, "alternate_set", new Asset { AlternateId = "abcd" });
var getNulls = await Client.Assets.ListAsync(
ResourceGroup,
MediaAccount,
new Microsoft.Rest.Azure.OData.ODataQuery<Asset>()
{
Filter = "properties/created gt 2022-10-07T00:00:00Z and properties/alternateId eq null"
});
Console.WriteLine("Nulls:");
Console.WriteLine(string.Join(',', getNulls.Select(s => s.Name)));
var getEmpty = await Client.Assets.ListAsync(
ResourceGroup,
MediaAccount,
new Microsoft.Rest.Azure.OData.ODataQuery<Asset>()
{
Filter = "properties/created gt 2022-10-07T00:00:00Z and properties/alternateId eq ''"
});
Console.WriteLine("Empty:");
Console.WriteLine(string.Join(',', getEmpty.Select(s => s.Name)));
var getNullOrEmpty = await Client.Assets.ListAsync(
ResourceGroup,
MediaAccount,
new Microsoft.Rest.Azure.OData.ODataQuery<Asset>()
{
Filter = "properties/created gt 2022-10-07T00:00:00Z and (properties/alternateId eq '' or properties/alternateId eq null)"
});
Console.WriteLine("Null Or Empty:");
Console.WriteLine(string.Join(',', getNullOrEmpty.Select(s => s.Name)));
var getAll = await Client.Assets.ListAsync(
ResourceGroup,
MediaAccount,
new Microsoft.Rest.Azure.OData.ODataQuery<Asset>()
{
Filter = "properties/created gt 2022-10-07T00:00:00Z"
});
Console.WriteLine("All:");
Console.WriteLine(string.Join(',', getAll.Select(s => s.Name)));

How check value existence in a deeply nested array in MongoDB.Driver C#?

As the following image, the collection is Posts. The _ids for the post and the comment are known.
So, How to check if a given value d exists in the AgreedUserIds?
Try this for single character search:
db.Posts.find(
{
_id: "b4d5...ff79",
Comments: {
$elemMatch: {
_id: "c1ea...d45",
AgreedUserIds: "d"
}
}
}
);
And this for multi character search:
db.Posts.find(
{
_id: "b4d5...ff79",
Comments: {
$elemMatch: {
_id: "c1ea...d45",
AgreedUserIds: { $in: ["c", "d"] }
}
}
}
);
If you want to keep it BsonDocument you have options to combine filters like this>
var client = new MongoClient();
var database = client.GetDatabase("test");
var collection = database.GetCollection<BsonDocument>("posts");
var postId = new BsonObjectId(new ObjectId("604b5ff389ff6887d1b91a93"));
var commentId = new BsonObjectId(new ObjectId("604b5ff389ff6887d1b91a92"));
var userId = "a";
//var userId = "e"; // not found
var postIdMatches = Builders<BsonDocument>.Filter.Eq("_id", postId);
var commentIdMatches = Builders<BsonDocument>.Filter.Eq("_id", commentId);
var userIdInside = Builders<BsonDocument>.Filter.AnyEq("AgreedUserIds", userId); // "a" in checking
var commentCheck = Builders<BsonDocument>.Filter.ElemMatch("Comments", userIdInside & commentIdMatches); // & combines filters. Also ElemMatch on any of the Comments is passing the criteria
var rows = (await collection.FindAsync<BsonDocument>(postIdMatches & commentCheck)).ToList();
You could also GetCollection<Post> with C# Post class describing the Post business object, and use .Any Linq query on that.

MongoDB Update nested Array object where there is a match in array document

Here is my MongoDB Document
{
"_id":20,
"GroupId":"45",
"Name":"Some Name",
"NestedArray":[
{
"Id":3,
"Name":"NesName",
"IsDeleted":false
}
]
}
I need to write a update statement like (in SQL interpretation)
update MyCollections.NestedArray set MyCollections.NestedArray[x].IsDeleted = true where MyCollections.NestedArray[x].Id = 3
Here is what I tried
var groupFilter = Builders<MyType>.Filter.Eq(x => x.Id, 45);
var nestedArayDocUpdate = Builders<MyType>.Update.Set(x => x.NestedArray[0].IsDeleted, true);
mongoDbRepository.UpdateMany(groupFilter, nestedArayDocUpdate,
new UpdateOptions {IsUpsert = false, BypassDocumentValidation = false});
using MongoDB 3.2 how can I come up with a MongoDB C# driver query?
This is how I ended up doing it.
var updateBuilder = Builders<Type>.Update.
.Set(x => x.NestedArray[-1].IsActive, false)
.Set(x => x.NestedArray[-1].IsDeleted, true);
mongoDbRepository.UpdateOne( Builders<Type>.Filter.Where(
x => x.NestedArray.Any(c => c.Id == categoryId)), updateBuilder);

Mongodb - How can I write a Push Upsert in c#?

I would like to implement the following command through c#. I've seen the Update.PushAll command but I'm not sure it's the right way. Any suggestion?
db.students.update(
{ name: "joe" },
{ $push: { scores: { $each: [ 90, 92, 85 ] } } }
, upsert = true
)
You can use PushAllWrapped to add an array of scores to your existing document:
var collection = db.GetCollection<Student>("students");
var query = Query<Product>.EQ(p => p.Name, "joe");
var push = Update<Student>.PushAllWrapped<int>(p => p.Scores, newScores);
collection.Update(query, push, UpdateFlags.Multi);
Using the new syntax, you can achieve using PushEach:
var collection = db.GetCollection<Student>("students");
var filter = Builders<Students>.Filter.Eq("name", "joe");
var update = Builders<Students>.Update.PushEach<Score>(x=>x.Scores, scores);
await collection.UpdateOneAsync(filter, update);

Mongo DB $near query in c#?

var query ="{'Geo':{'$near': {'$geometry': {'type': 'Point' ,'coordinates':[]} }}}";
var parsing = BsonDocument.Parse(query);
var qwithcoor = parsing["Geo"]["$near"]["$geometry"]["coordinates"].AsBsonArray;
qwithcoor.AddRange(coordinates);
parsing["Geo"]["$near"].AsBsonDocument.Add("$maxDistance", radius);
var collection = database.GetCollection<BsonDocument>("mycollection");
var documents = await collection.Find(parsing).ToListAsync();
I want to do this with Builders<BsonDocument>.Filter. Like this:
var query=Builders<BsonDocument>.Filter.Near();
var documents=await collection.Find(query).ToListAsync();
do I use Near after the Filter? What are the Near parameters?
I solve this with
var gp =new GeoJsonPoint<GeoJson2DGeographicCoordinates>(new GeoJson2DGeographicCoordinates(coordinates[0], coordinates[1]));
var query=Builders<BsonDocument>.Filter.Near("Geo",gp,radius);
var result = await col.Find(query).ToListAsync();

Categories

Resources