In a MongoDB I have a collection with documents with this structure:
{
"_id" : 18,
"name" : "Verdell Sowinski",
"scores" : [
{
"type" : "exam",
"score" : 62.12870233109035
},
{
"type" : "quiz",
"score" : 84.74586220889356
},
{
"type" : "homework",
"score" : 81.58947824932574
},
{
"type" : "homework",
"score" : 69.09840625499065
}
]
}
I am using .NET. I need to remove the scores array element with the lowest scores.score for all the documents with scores.type="homework".
In the example would be the 4th element of the scores array ("score" : 69.09840625499065).
I suposse I have to group by Id, sort limiting to 1 and then use the method DeleteMany but I can´t get the code work
I can`t solve the problem. The code I´m trying and don't work is the next one:
var db = client.GetDatabase("school");
var col = db.GetCollection<Student>("students");
var filter = new BsonDocument("scores.type", "homework");
var myresult = await col
//.Find(filter)
.Aggregate()
.Unwind(x => x.Scores)
.Group(new BsonDocument { { "_id", "$_id" },
{ "minimo", new BsonDocument("$min", "$Scores.score") } })
.Sort(new BsonDocument("minimo", -1))
.Limit(1)
.ToListAsync();
My classes:
public class Student
{
public int _id { get; set; }
public string Name { get; set; }
public List<Score> Scores { get; set; }
}
public class Score
{
public string Type { get; set; }
public double Mark { get; set; }
}
Related
I have a problem with querying data from a self reference datatable having an ICollection.
Here are my table structures:
public class SoqHeading
{
public int Id { get; set; }
public string ItemNo { get; set; }
public string Heading { get; set; }
public SoqRevision SoqRevision_NP { get; set; }
public ICollection<SoqItem> Items { get; set; }
public int? ParentSoqHeadingId { get; set; }
public SoqHeading Parent_NP { get; set; }
public ICollection<SoqHeading> Children_NP { get; set; }
}
public class SoqItem
{
public int Id { get; set; }
public SoqPreliminaryOrContract_enum PreliminaryOrContract { get; set; }
public int SoqHeadingId { get; set; }
public SoqHeading SoqHeading_NP { get; set; }
}
I have a self referenced relation in the SoqHeading table which is 1 to many. The SoqHeading table can have zero or many SoqItems.
This is how the data is in my database
what i want is to query all from the root node of the SoqHeading table with its children and the items.
like this
{
"ItemNo": "C",
"Items": [
{
"ItemNo": "c-1",
},
{
"ItemNo": "c-2",
}
],
"Children_NP": [
{
"ItemNo": "C.1",
"Children_NP": [
{
"ItemNo": "C.1.1",
"Items": [
{
"ItemNo": "c.1.1-1",
},
{
"ItemNo": "c.1.1-2",
}
],
"Children_NP": [],
},
{
"ItemNo": "C.1.2",
"Items": [
{
"ItemNo": "c.1.2-1",
},
{
"ItemNo": "c.1.2-2",
}
],
"Children_NP": [],
}
],
},
{
"ItemNo": "C.2",
"Children_NP": [],
}
]
}
But currently i get data from the query like this
[
{
"ItemNo": "C"
},
{
"ItemNo": "C.1.2",
}
]
where C.1.2 has to be inside C, but it not. C and C.1.2 are in the same level which i dont wont to have produced by the following query
var entity = await _context.SoqHeadings
.Include(i=>i.Items)
.Include(i => i.Children_NP)
.Where(w => w.SoqRevision_NP.ProjectId == 10)
.ToListAsync();
please help
so it seems to be EFcore has no support to included the children on the first child node https://github.com/dotnet/efcore/issues/14144
so the work around is something like this here https://khalidabuhakmeh.com/recursive-data-with-entity-framework-core-and-sql-server
I have two tables, which have following foreign key
Poll(CreatedBy) --> CreateBy(ID)
On performing join, I am getting data as following:
I want to write an query using EF (if possible) to return result as:
[{
"id": 1,
"users": [
{
"email": "abc.com"
}
]
},
{
"id": 3,
"users": [
{
"email": "xyz.test"
},
{
"email": "tet.com"
}
]
}]
Assuming that the class structure like below:
public class Poll
{
public int ID { get; set; }
public string Name { get; set; }
public List<CreateBy> CreateBy { get; set; }
}
public class CreateBy
{
public int ID { get; set; }
public string EmailAddress { get; set; }
public string DisplayName { get; set; }
[ForeignKey("Poll")]
public int PollId { get; set; }
}
Data source:
Linq query:
var result = (from p in _context.Poll.ToList()
join c in _context.CreateBy on p.ID equals c.PollId
group p by p.ID into g
select new
{
id = g.Key,
users = g.Select(x => x.CreateBy.Where(z => z.PollId == g.Key).Select(y => new { email = y.EmailAddress })).FirstOrDefault()
}).ToList();
Result:
I am trying to get a specific value from a Bson document using an IQueryable object. I have a method that is reading a json structure as shown below.
"SimulatedData": [
{
"value": 1819.00923045901,
"units": "hp",
"tag": "comp/totalIhp",
"name": "Compressor - Total IHP"
},
{
"value": 789.294125,
"units": "RPM",
"tag": "comp/averageSpeed",
"name": "Compressor - Speed"
},
{
"value": 2064.74658240481,
"units": "hp",
"tag": "comp/totalBhp",
"name": "Compressor - Total BHP"
}
]
I am reading this JSON, getting the 'tag' key value and then looking for this tag value in a collection in MongoDB.
try
{
string jsonFromFile;
using (var reader = new StreamReader(path))
{
jsonFromFile = reader.ReadToEnd();
}
var simulatedData = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonFromFile);
foreach (var channel in simulatedData.SimulatedData)
{
var tag = channel.tag;
var master = DBConnect.CosmosClient.GetCollection<MasterVariables>("MasterVariables");
var channelId = master.AsQueryable().Where(x => x.Tag == $"{tag}");
foreach(var c in channelId)
{
string id = c.ChannelID;
Console.WriteLine(id);
}
}
}
The value of the 'tag' key will be used to search in MasterVariables for a match. The document in MasterVariables that matches the value of the 'tag' key will result in a JSON/bson as below.I have a class that take in these values and sets them to class attributes
{
"Tag" : "comp/idealTotalSucCapacity",
"Group" : "{ id : \"comp\", parent : \"#\", text : \"Compressor\" }",
"Series" : "Compressor",
"Enabled" : true,
"ChannelID" : "C8",
"productType" : "Spotlight_Comp",
"database" : "compdata"
}
MasterVariables class (below)
public class MasterVariables
{
public string Tag { get; set; }
public string Group { get; set; }
public string Series { get; set; }
public bool Enabled { get; set; }
public string ChannelID { get; set; }
public string productType { get; set; }
public string database { get; set; }
}
My main issue is that I am not able to get the "ChannelID" value using c.ChannelID . My code compiles and doesn't give me any errors. But I am very confused as to why I am not able to get the channelID value using an Iqueryable object. I know the below foreach isn't correct since I will only be receiving 1 Bson document that matches the 'tag' value. But I haven't found anything helpful about a different way to get the ChannelId. Any thoughts on what I am doing wrong here? Or is there a different approach?
foreach(var c in channelId)
{
string id = c.ChannelID;
Console.WriteLine(id);
}
I have a little bit problem with an data update in mongoDB. I have an array embedded in an other array who is embedded in a document (yaaaaay ^^). So my collection is like that :
{
"_id" : ObjectId("5965e0b4f1042c4c3f1d8edc"),
"Builder" : "Google",
"Family" : "Car",
"ProductName" : "ABCD_80A_PU170017",
"ProductNumber" : "N 1",
"Test" : [
{
"Num_Test" : "PU170017",
"Date_Start" : ISODate("2017-07-12T00:00:00.000Z"),
"Bench": [
{
"Room": 1,
"Num" : 1,
"Designation" : "AC1; AC3",
"IP" : "123.456.78.9",
"Capacity" : 12,
}
],
"User" : [
{
"Number" : "EBBW396",
"Password" : "titi",
"Name" : "NDJO",
"Surname" : "Charles",
"Tel" : "06XXXXXX",
"isAdmin" : true
}
]
}
]
}
And i want to insert a new array embedded in "Test".
So i found my happiness here : https://docs.mongodb.com/getting-started/csharp/update/ AND How to use C# to insert document into existing embedded documents?
And i have write this code :
static void Main(string[] args)
{
IMongoClient client = new MongoClient("mongodb://10.194.157.199:27017");
IMongoDatabase database = client.GetDatabase("PINEA");
IMongoCollection<Product> collection = database.GetCollection<Product>("Product");
var filter = Builders<Product>.Filter.Eq("Test.Num_Test", "PU170017");
var meter = new Meter();
meter.Value= 12;
meter.Date = DateTime.Now;
var meterList = new List<Meter>();
meterList.Add(meter);
var update = Builders<Product>.Update.Push("Result", new Result
{
MeterList = meterList
});
var result = collection.UpdateOne(filter, update);
}
But nothing happens, nothing has added or modified. I miss something important but i don't understand what is it.
Finally, here are my classes:
class Result
{
public List<Meter> MeterList { get; set; }
public List<Problem> Problem { get; set; }
}
class Meter
{
public int? Value { get; set; }
public DateTime? Date { get; set; }
}
class Test
{
public string Num_Test { get; set; }
public DateTime? Date_Start { get; set; }
public List<Bench> Bench { get; set; }
public List<User> User { get; set; }
public List<Result> Result { get; set; }
}
class Product
{
public string Builder { get; set; }
public string Fammily { get; set; }
public string ProductName { get; set; }
public string ProductNumber { get; set; }
public List<Test> Test { get; set; }
}
To explain the context, I need to update the array "result" regularly and maintain data arborescence like that. After the end of the test, data aren't modify anymore.
PS : I'm still a student but I work part time
Thanks
I am wanting to edit an element that might exist in multiple arrays in a collection.
public class Class
{
[BsonId]
public Guid Id { get; set;}
public string Name {get; set;}
public List<Student> Students {get; set;}
}
public class Student
{
[BsonId]
public Guid Id {get; set;}
public string Name {get; set;}
public string Grade {get; set;}
}
Then my class collection would look like
{
"_id" : NUUID("..."),
"Name" : "Computer Science",
"Students" : [
{
"_id" : NUUID("..."),
"Name" : "Chris"
"Grade" : "A"
},
{
"_id" : NUUID("..."),
"Name" : "Bob"
"Grade" : "B"
}
}
And my student collection would look like
{
"_id" : NUUID("..."),
"Name" : "Chris Eastwood"
"Grade": "C
}
Now when a student updates his information I want his information to be updated in each class.
I was trying to do:
// given student that has been edited
var query = Query.EQ("Students._id", student.Id);
var update = Update<Class>
.Pull(c => c.Students, x => x.EQ(q => q.Id, student.Id))
.Push(c => c.Students, student)
Context.Class.Update(query,update,UpdateFlags.Multi);
But that does not work since you "cannot update Students and Students at the same time"
I was wondering is there a way to just update all that student in each array for each Class that contains that Student?
Thanks!
I'm not familiar with the c# driver, but this is the query that you are looking for:
db.classes.update({
'Students._id': some_student_id,
}, {
$set: {
'Students.$.property': some_value
}
},{
multi: true
});
The key concept that you are looking for is the positional $ operator. It is the index of the object that matched in the query.