MongoDB: Editing Element In Array - arrays

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.

Related

How to get a specific value from a MongoDb document

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);
}

EFCore: Query a related entity based on the maximum value in a field in the related entity

I need to query a related entity based on the maximum value in a field in the related entity, and then display results from that item.
For example, the models are defined:
public class Student
{
public int StudentID {get; set;}
public string Name {get; set;}
public ICollection<ReportCard> ReportCards {get; set;}
}
public class ReportCard
{
public int ReportCardID {get; set;}
public int ProjectID { get; set; }
public Project Project { get; set; }
public int Result {get; set;}
public int Comment {get; set;}
public DateTime PublishDate {get; set;}
}
In the razor controller:
public class LatestResultsModel : PageModel
{
...
public IList<Student> Students {get; set;}
public async Task<IActionResult> OnGetAsync()
{
Students = await _context.Student
.Include(student => student.ReportCard)
.ToListAsync();
}
}
In the razor view:
#foreach (Student student in Model.Students)
{
<p>#student.Name</p>
<p>#student.ReportCard.Max(i => i.PublishDate).Result.ToString()</p>
}
After the Max statement I cannot query the other fields.
I've tried a few things to achieve this outcome of filtering the related data.
Filtered Includes are not supported.
Is there some type of join that could achieve this outcome?
It also doesn't handle the situation when a Student has no ReportCard. InvalidOperationException: Nullable object must have a value.
After the Max statement I cannot query the other fields. I've tried a few things to achieve this outcome of filtering the related data.
Yes! You cannot! because Max statement select only the field that you mention in the Max.
It also doesn't handle the situation when a Student has no ReportCard. InvalidOperationException: Nullable object must have a value.
Do as follows to overcome both problems:
#foreach (Student student in Model.Students)
{
<p>#student.Name</p>
if(student.ReportCards.Count > 0)
{
<p>#student.ReportCards.OrderByDescending(rc => rc.PublishDate).FirstOrDefault().Result.ToString()</p>
<p>#student.ReportCards.OrderByDescending(rc => rc.PublishDate).FirstOrDefault().PublishDate.ToString()</p>
}
else
{
<p>Student has no report card!</p>
}
}

How insert new array into existing embedded array in C#?

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

Delete array elements in a embebbed document

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; }
}

Enum as Key in RIA Services

In my entity class i use enum as a key property:
[DataContract]
public class MultimediaType
{
[DataMember]
[Key]
public Identificator Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
[DataContract]
public enum Identificator
{
[EnumMember]
Image = 1,
[EnumMember]
Video = 2,
[EnumMember]
Sound = 3
}
}
[EnableClientAccess()]
public class DomService : DomainService
{
List<MultimediaType> _multimediaTypes = new List<MultimediaType>()
{
new MultimediaType()
{
Id = MultimediaType.Identificator.Image,
Name = "Image",
Description = "This is type for all images."
},
new MultimediaType()
{
Id = MultimediaType.Identificator.Video,
Name = "Video",
Description = "This is type for all videos."
},
new MultimediaType()
{
Id = MultimediaType.Identificator.Sound,
Name = "Sound",
Description = "This is type for all sounds."
},
};
[Query]
public IQueryable<MultimediaType> GetMultimediaTypes()
{
return _multimediaTypes.AsQueryable();
}
}
My client is SilverLight application that consume my domain service.
I have no idea what is wrong, but i obtaint this error:
The property 'MultimediaType.Id' is marked as a key property, but it's not serializable. Are you missing DataMemberAttribute?
Do you have any idea what i do wrong? Thanks a lot!
EnumMemberAttribute : Specifies that the field is an enumeration member and should be serialized.
Check the below lins :
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.enummemberattribute(v=vs.95).aspx
Sharing Enum with WCF Service
Also take a look at the Remarks and Example

Resources