I have the following document:
{
"_id": {
"$oid": "5fc232d9b9b390623ce498ee"
},
"trigger": {
"type": 0,
"interval": 15
},
"startTime": {
"$numberLong": "1608078905"
},
"state": 0,
"assigned_to": ""
}
And I have a UpdateMany statement that only updates documents that their startTime (timespan) + interval (seconds) is lower than equal to the current timestamp with the value of 'computer a', (UPDATE) and set the 'state' attribute to '1':
(UPDATE)
db.mycollection.updateMany(
{ state: 0 },
[
{ $set: { assigned_to: { $switch: {
branches: [
{ case: { $lte: [ { $add: [ "$startTime", "$trigger.interval" ] }, new Timestamp() ] }, then: "computer a" }
],
default: ""
} } } },
{ $set: { state: 1 } }
]
)
My goals are:
(RESOLVED) To update the state to '1' in addition to the 'assigned_to' field
(RESOLVED) To automatically calculate the timestamp (the current time)
Eventually, to have it working with my C# .NET Core application (if possible - with the driver syntax so it will be strongly-typed)
On the C# side I've tried the following (with no success):
var results = _jobs.UpdateMany(
f => (f.StartTime + f.Trigger.Interval) <= DateTimeOffset.Now.ToUnixTimeSeconds(),
o => o.AssignedTo == "computer a");
Another approach I tried:
var builder = Builders<Job>.Filter;
var filters =
builder.Lte(o => o.StartTime + o.Trigger.Interval, DateTimeOffset.Now.ToUnixTimeSeconds()) &
builder.Eq(o => o.AssignedTo, string.Empty);
var updateDefinition =
Builders<Job>.Update.Set(x => x.AssignedTo, Environment.MachineName);
var result = _jobs.UpdateMany(filters, updateDefinition);
After spending hours, I only achieve the UpdateMany statement above working.
If you have ideas about how it could be done in a better way - I'm free for offers.
Related
i am new on MongoDB and i am trying to use it in C# context. Let´s say, i have documents like this:
[
{
"Number": "2140007529",
"Name": "ABC",
"IsInactive": true,
"EntryList": [
{
"Timestamp": "2022-06-01T14:00:00.000+00:00",
"Value": 21564.0
},
{
"Timestamp": "2022-07-01T21:31:00.000+00:00",
"Value": 21568.0
},
{
"Timestamp": "2022-08-02T21:21:00.000+00:00",
"Value": 21581.642
},
{
"Timestamp": "2022-09-02T15:42:00.000+00:00",
"Value": 21593.551
},
{
"Timestamp": "2022-09-26T13:00:00.000+00:00",
"Value": 21603
}
]
},
{
"Number": "2220000784",
"Name": "XYZ",
"IsInactive": false,
"EntryList": [
{
"Timestamp": "2022-09-26T13:00:00.000+00:00",
"Value": 0.0
},
{
"Timestamp": "2022-10-01T08:49:00.000+00:00",
"Value": 5.274
},
{
"Timestamp": "2022-11-01T09:56:00.000+00:00",
"Value": 76.753
},
{
"Timestamp": "2022-12-01T19:43:00.000+00:00",
"Value": 244.877
},
{
"Timestamp": "2023-01-01T11:54:00.000+00:00",
"Value": 528.56
},
{
"Timestamp": "2023-02-01T17:21:00.000+00:00",
"Value": 802.264
}
]
}
]
I want to get the document where the IsInactive flag is false. But for the EntryList there should be returned entries greater than Timestamp 2022-12-31 only.I should look like this:
{
"Number": "2220000784",
"Name": "XYZ",
"IsInactive": false,
"EntryList": [
{
"Timestamp": "2023-01-01T11:54:00.000+00:00",
"Value": 528.56
},
{
"Timestamp": "2023-02-01T17:21:00.000+00:00",
"Value": 802.264
}
]
}
So, here is my question. How can i filter nested arrays in return value with C#. Thanks for help!
I tried to get the result with aggregate function of MongoDB in MongoDB Compass. I got it work with but not in C#.
I think you are looking for a query similar to this one.
So you can try something like this code:
var desiredTimestamp = new DateTime(2022, 12, 31);
var results = collection.AsQueryable()
.Where(x => x.IsInactive == false && x.EntryList.Any(e => e.Timestamp >= desiredTimestamp))
.Select(obj => new
{
Number = obj.Number,
Name = obj.Name,
IsInactive = obj.IsInactive,
EntryList = obj.EntryList
.Where(e => e.Timestamp >= desiredTimestamp)
.ToList()
}).ToList()
Note that I'm assuming your Timestamp is a date type, otherwise you can't compare date and string.
I am having a small problem in some LINQ I am writing
public async Task<BookingEntry[]> AuditInvoiceForAPI(BookingSearchFilter filter)
{
if (filter == null)
throw new ArgumentNullException();
using var speedPayDbContext = this.speedPayDbContextFactory();
var results = await speedPayDbContext.spAuditInvoiceForAPI(filter.BookingID, filter.VendorID, filter.InvoiceID).ToArrayAsync();
var BookingResponse = results
.Select(r =>
{
return new BookingEntry()
{
Result = r.Result,
BookingID = r.BookingID,
Balance = r.Balance,
TotalCost = r.TotalCost,
CostDetails =
results.Where(cd => cd.BookingID == r.BookingID)
.Select(a => new Costdetail(a.Amount, a.ChargeCodeID)).ToArray(),
Message = r.Message,
};
})
.ToArray();
return BookingResponse;
here is the result set
BookingId
Result
Message
TotalCost
BillKey
Balance
ChargeCodeId
amount
8446670
0
Success
498.54
8446670
89.8000
11
75.00
8446670
0
Success
498.54
8446670
89.8000
14
14.80
I am getting dup in the JSON which I can understand why. There are indeed two rows returned one booking entry with two costdetails.
Can someone please help me with get rid of the dup?
Its probably as simple as I don't understand SelectMany.
This is in essence a simple join first 6 columns are the header and the last two are the detail records and you can see that the bookingID is what they are joined on.
Thanks very much
{
"bookingID": "8446670",
"result": "0",
"message": "Success",
"totalCost": 498.54,
"balance": 89.8,
"costDetails": [
{
"chargeCodeID": 11,
"amount": 75
},
{
"chargeCodeID": 14,
"amount": 14.8
}
]
},
{
"bookingID": "8446670",
"result": "0",
"message": "Success",
"totalCost": 498.54,
"balance": 89.8,
"costDetails": [
{
"chargeCodeID": 11,
"amount": 75
},
{
"chargeCodeID": 14,
"amount": 14.8
}
]
}
]
Please let me know the C# equivalent of below MongoDB query. It works fine in Robo3T for MongoDB
db.UserProfile.aggregate([
{
$project: {
SName:1,
FName:1,
DemRole: {
$filter: {
input: "$DemRole",
as: "item",
cond: { $eq: [ "$$item.Name", "FO" ] }
}
}
}
}
])
I could achieve this by below C# code
var stage1 = "{ $project: { SName: 1, FName: 1, DemRole: { $filter: { input: '$DemRole', as: 'item', cond: { $eq: ['$$item._id', '5bc49241f12541c3aaa098ee' ] } } } } }";
var query = collection.Aggregate(new AggregateOptions() { AllowDiskUse = true })
.AppendStage<BsonDocument>(stage1).ToEnumerable();
return query?.Select(point => BsonSerializer.Deserialize<RetUserProfile4Role>(point)).ToList();
I have two arrays
"commanditaires_data": [
{
"id": "254",
"level": 78
},
{
"id": "255",
"level": 22
}
]
"commanditaires_data": [
{
"id": "254",
"level": 78
}, {
"id": "255",
"level": 22
},
{
"id": "255",
"level": 22
}
]
I don't manage to get the missing items in the first array.
I need to do a differential between these two arrays.
I tried to use Except() but I send me every items of the first arrays
I'm using JSON.NET so my vars for arrays are :
var srcObjs = source.Children().ToList().OfType<JObject>();
var tarObjs = target.Children().ToList().OfType<JObject>();
var diff = tarObjs.Except(src.objs);
=> It sends me all items in tarObjs.
I need to handle many cases :
If srcObjs.Count() < tarObjs.Count() //Added item(s)
If srcObjs.Count() > tarObjs.Count() // Deleted item(s)
Else //Edited Item(s)
I also tried to use linq but without success
public class CommanditairesEqualityComparer: IEqualityComparer<Commanditaires>
{
public bool Equals(Commanditaires first, Commanditaires second)
{
if (first== null && first== null)
return true;
return first.Id == second.Id
&& first.Level == second.Level;
}
public int GetHashCode(Commanditaires model)
{
return model.Id.GetHashCode() + model.Level.GetHashCode();
}
}
and then
var comparer = new CommanditairesEqualityComparer();
var distinctItems = firstList.Except(secondList, comparer );
I made the following linq statement
C#
var list = from row in repository.GetAllEntities()
group row by new { row.RegionString, row.SubRegionString, row.CountryString } into g
select new { g.Key.RegionString, g.Key.SubRegionString, g.Key.CountryString, Count = g.Count() };
return Json(list, JsonRequestBehavior.AllowGet);
That returns
[
{
"RegionString":"Americas",
"SubRegionString":"",
"CountryString":"",
"Count":2
},
{
"RegionString":"Americas",
"SubRegionString":"NorthAmerica",
"CountryString":"Canada",
"Count":5
},
{
"RegionString":"Americas",
"SubRegionString":"NorthAmerica",
"CountryString":"US",
"Count":3
},
{
"RegionString":"Americas",
"SubRegionString":"SouthAmerica",
"CountryString":"Chile",
"Count":3
},
{
"RegionString":"EMEA",
"SubRegionString":"AsiaPacific",
"CountryString":"Australia",
"Count":2
},
{
"RegionString":"EMEA",
"SubRegionString":"AsiaPacific",
"CountryString":"Japan",
"Count":1
},
{
"RegionString":"EMEA",
"SubRegionString":"SouthernEurope",
"CountryString":"Turkey",
"Count":1
},
{
"RegionString":"EMEA",
"SubRegionString":"WesternEurope",
"CountryString":"",
"Count":1
}
]
But I am trying to make it into this format
[{
name: "Americas",
children: [
{
name: "NorthAmerica",
children: [{ "name": "Canada", "count": 5 },
{ "name": "US", "count": 3 }]
},
{
name: "SouthAmerica",
children: [{ "name": "Chile", "count": 1 }]
},
],
},
{
name: "EMA",
children: [
{
name: "AsiaPacific",
children: [{ "name": "Australia", "count": 2 },
{ "name": "Japan", "count": 1 }]
},
{
name: "SouthernEurope",
children: [{ "name": "Turkey", "count": 1 }]
},
],
}]
How could I modify the statement to get the result I'm looking for? Non linq answers are acceptable too.
EDIT: Region is the parent of SubRegion, SubRegion is the parent of Country and Count is the unique number of items that belongs to Country
Here is the linq query you want (I've removed the -String postfix for readability):
var list =
from entity in repository.GetAllEntities()
group entity by entity.Region into regions
let childrenOfRegions =
from region in regions
group region by region.SubRegion into subregions
let countriesOfSubRegions =
from subregion in subregions
group subregion by subregion.Country into countries
select new { Name = countries.Key }
select new { Name = subregions.Key, Children = countriesOfSubRegions }
select new { Name = regions.Key, Children = childrenOfRegions };
There is no Count in this query, since I don't really understand what you are counting.
What I'm doing here is grouping the rows into Regions and in the last line you can see the
select new { Name = regions.Key, ... } part where I'm returning the Regions.
To get the children, you need to group the Regions into SubRegions (the same way with Regions). You repeat this all the way down to the Countries and you're done.