MongoDB String to Date? - mongodb

Following is the JSON of the data:
{
projectName: String,
projectDescription: String,
users: [
],
projectManager: [
],
teamLead: [
],
createdBy: String,
superAdmin: String,
createdAt: Date,
task: [
{
userID: String,
name: String,
taskName: String,
nohrs: Number,
description: String,
comments: String,
date: String,
from: String,
to: String,
lastUpdatedDate: String
}
]
}
The array of task contains many tasks for each project. And each task has a date in string format. I need to convert each string date to ISO date format.
How can we achieve this?
I have tried this :
db.projects.find({}).forEach(function(task){
task.date = new Date(task.date);
db.collection.save(task);})
but this is adding a column date and not editing the date in task array?

You were really close to the solution. The correct code snippet would be:
db.projects.find({}).forEach(function(project){
project.task.forEach(function(task){
task.date = new Date(task.date);
});
db.projects.save(project);
})
You needed one more loop in your code :)

Well guys this worked
db.projects.find({}).forEach(function(project){
project.task.forEach(function(task){
// printjson(task)
task.date = new Date(task.date);
print(task.date)
db.projects.save(project);
})})

db.projects.find({},function(err,data){
//this find query will return the array of documents through which we need to iterate
for(var i =0; i<data.length;i++){
//then we want convert the date string into Date we need to iterate task array with in each document.
for(var j = 0;j<data[i].task.length;j++){
data[i].task[j].date = new Date(data[i].task[j].date);
}
}
//now save the new data
data.save();
})

Related

MongoDB doesn't save document when timestamps are initialized in struct

I am having a very weird issue when trying to save a data in Mongodb by the Rust driver. This is my struct
#[derive(Deserialize, Serialize, Debug)]
struct Info {
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
id: Option<bson::oid::ObjectId>,
name: String,
created_at: i64,
updated_at: i64,
}
And this is my actix route handler function
async fn post_request(info: web::Json<Info>, data: web::Data<State>) -> impl Responder {
let name: &str = &info.name;
let document = Info {
id: None,
name: name.to_string(),
created_at: Utc::now().timestamp_millis(),
updated_at: Utc::now().timestamp_millis(),
};
// Convert to a Bson instance:
let serialized_doc = bson::to_bson(&document).unwrap();
let doc = serialized_doc.as_document().unwrap();
let collection = data.client.database("test1").collection("users");
let result = collection.insert_one(doc.to_owned(), None).await.unwrap();
HttpResponse::Ok().json(result).await
}
I am getting the Utc struct by chrono crate.
When i am trying to save the data in MongoDB by hitting the route, It doesn't gets saved. But, oddly, when i comment out the created_at and updated_at in struct and handler, it gets saved. If i don't use structs and try to save it as a raw document, by storing created_at and updated_at in variables, then also it gets saved, but not by structs. I am new to rust so maybe i am doing something wrong. Please help

Swift - Array to Dictionary

So, I have the following objects:
struct Person {
let name: String
let birthday: String
}
let Bob = Person(name: "Bob", birthday: "11.12.1987")
let Tim = Person(name: "Tim", birthday: "11.12.1987")
let John = Person(name: "John", birthday: "01.02.1957")
let Jerry = Person(name: "Jerry", birthday: "17.12.2001")
And the following array:
let people = [Bob, Tim, John, Jerry]
My goal is to generate a dictionary from this array, with "birthday" for the key and the "Person" object itself as the value: [String: [Person]]. If there are equal keys the person should be added and form an array as a key. So the result will be the following:
dictionary = ["11.12.1987": [Bob, Tim], "01.02.1957": John, "17.12.2001": Jerry]
What is the best way to achieve this?
Cheers!
You could use Dictionary(grouping:by:) method together with mapValues,
let result = Dictionary(grouping: people, by: \.birthday)
print(result)
Output is,
["01.02.1957": ["John"], "17.12.2001": ["Jerry"], "11.12.1987":
["Bob", "Tim"]]
This would yield you a Dictionary of type Dictionary<String, [Person]>.
From, your question it seems like you want a Person if there is only one Person and array when there are multiple people. You would loose type in that situation and your type would be something like this, Dictionary<String, Any>. You could make small bit of modification to the above code to do that.
let result = Dictionary(grouping: people, by: \.birthday)
.mapValues { people -> Any in
if people.count == 1 {
return people.first!
}
return people
}
print(result)
The output would be similar to what you want,
["01.02.1957": "John", "17.12.2001": "Jerry", "11.12.1987": ["Bob",
"Tim"]]
What about a loop through the dictionary checking if date exists. Otherwise create key with date and assign value.
If key already exists append person to the actual key value:
var dictionary = [String: [Person]]()
// Loop through all person objects in array
for person in people {
// Check if date already exists
if dictionary[person.birthday] != nil {
// If already exists, include new person in array
var array = dictionary[person.birthday]
array!.append(person)
}
// If date does not exists, add new key with date and person
else {
dictionary[person.birthday] = [person]
}
}

How can I properly display a much readable output using sorting?

The output of my code is all good, it is already sorted, but the problem is that, it contains some garbage value that I do not need, I will provide the example output of it.
Here is my code:
struct Student {
var id: Int = 0;
var name: String = String();
var course: String = String();
var GPA: Float = 0.0;
}
let student = [
Student(id: 201520032, name: "Ton Agnis", course: "BSITWMA", GPA: 3.69),
Student(id: 201620122, name: "Juan Cruz", course: "BSCSSE", GPA: 2.23),
Student(id: 201723214, name: "Pedro Sy", course: "BSITAGD", GPA: 2.87),
Student(id: 201418492, name: "Phot xPro", course: "BSCPE", GPA: 3.99)
]
func stud(get studs:[Student]){
print("Student No.\t\tID\t\tName\t\t\tCourse\t\tGPA")
for i in 0...studs.count - 1{
print("Student \(i+1) \t \(student[i].id)\t\(student[i].name)\t\t\(student[i].course)\t\t\(student[i].GPA)")
}
}
let x = student.sorted{ $0.GPA < $1.GPA }
stud(get: student)
print(x)
Here is the Output of the Given Code
As you can see the output displays some values that is not needed.
What I want to be displayed is a better readable sorted of values given.
Thank You!
If you make your custom classes conform to the CustomStringConvertible protocol (add a single computed variable, description, of type String) then when you print one of those objects it displays nicely formatted.
You could use the formatting of your print statement with tabs as the starting point.
The function stud is already printing your student array in a formatted way.
Remove print(x) at the end of the code you posted to get a clean output.
Edit:
Also if I understand correctly your needs, you want to print the sorted list of students by GPA. (x in your code)
You can do it by passing x to the stud function and by fixing the stud function to use the function parameter instead of student var.
struct Student {
var id: Int = 0;
var name: String = String();
var course: String = String();
var GPA: Float = 0.0;
}
let student = [
Student(id: 201520032, name: "Ton Agnis", course: "BSITWMA", GPA: 3.69),
Student(id: 201620122, name: "Juan Cruz", course: "BSCSSE", GPA: 2.23),
Student(id: 201723214, name: "Pedro Sy", course: "BSITAGD", GPA: 2.87),
Student(id: 201418492, name: "Phot xPro", course: "BSCPE", GPA: 3.99)
]
func stud(get studs:[Student]){
print("Student No.\t\tID\t\tName\t\t\tCourse\t\tGPA")
for i in 0..<studs.count {
print("Student \(i+1) \t \(studs[i].id)\t\(studs[i].name)\t\t\(studs[i].course)\t\t\(studs[i].GPA)")
}
}
let x = student.sorted{ $0.GPA < $1.GPA }
stud(get: x)

SWIFT append data to dictionary

I'm having trouble coding an apparently simple task. I want to add new client profile data to a client profile dictionary (clientDatabase) but keep getting errors - can't seem to append - error: value of type '(String: clientProfile)' has no member 'append' (see error at bottom of code)
Any insights you can provide are greatly appreciated.
Thanks,
Bill
//: Playground - noun: a place where people can play
import UIKit
import Foundation
/*
code copied from B-C Dev Database - structs but simplified with fewer variables
goal is to getappend new client to work.
*/
/*
Globals: these go in main.swift file
*/
struct clientProfile {
var firstName: String = ""
var lastName: String = ""
var group: Int = 0
}
//var clientDatabase : NSMutableDictionary! = [String:clientProfile]()
var clientDatabase:[String:clientProfile]
/* sample data template: phone is key, sub array is;
(firstName: "", lastName: "",pilatesGroup: )
*/
clientDatabase = [
"1234567": clientProfile(firstName: "Sally", lastName: "Sillious", group: 3),
"2345678": clientProfile(firstName: "Sue", lastName: "Parker",group: 8),
"3456789": clientProfile(firstName: "Bob", lastName: "Parker", group: 2),
"5678901": clientProfile(firstName: "Jim", lastName: "Beam", group: 12)
]
clientDatabase.count
// so far so good
/*
add new client
declare local variables in scene swift files where used
*/
var firstName: String = ""
var phone:String = ""
var newPhone: String = ""
var newFirstName: String = ""
var newLastName: String = ""
var newGroup: Int = 0
// define struct using these input variables for values but with same keys as (global) clientDatabase
struct newClientProfile {
var firstName: String = newFirstName
var lastName: String = newLastName
var group: Int = newGroup
}
// put newClientProfile into newClientDictionary
var newClientDatabase:Dictionary = [String:newClientProfile]()
// input values from scene - UITextFields
newPhone = "4567890"
newFirstName = "Super"
newLastName = "Dave"
newGroup = 14
// test that all values are where they should be
clientDatabase
clientDatabase.count
newClientDatabase = [newPhone:newClientProfile()]
newClientDatabase.count
// ok so far
//the following line returns an error
clientDatabase.append(newClientDatabase)
// can't seem to append - error value of type '(String: clientProfile)' has no member 'append'
Two things. First of all clientDatabase is a dictionary which doesn't have append, instead you'll have to iterate through the other dictionary and insert its elements into clientDatabase.
The other issue is that clientDatabase and newClientDatabase aren't the same type. The first one is [String : clientProfile] and the second is [String : newClientProfile]. You'll have to convert the values from one type to the other to combine the dictionaries.
Looking deeper into the code there some misunderstandings about the language. For example:
struct newClientProfile {
var firstName: String = newFirstName
var lastName: String = newLastName
var group: Int = newGroup
}
// put newClientProfile into newClientDictionary
var newClientDatabase:Dictionary = [String:newClientProfile]()
You're creating a struct just for the purpose of containing a single set of values when you already have clientProfile. Instead you could do:
var newClientProfile = clientProfile(firstName: newFirstName, lastName: newLastName, group: newGroup)
This will create a variable which is an instance of clientProfile and stores the information you want. However, you have the other variables defined as empty values.
Here's a cleaned up version of your code, take a look at it and let me know if you have any questions.
struct ClientProfile { // Convention is to use initial caps for enum, struct, class
let firstName: String
let lastName: String
let group: Int
}
var clientDatabase = [
"1234567": ClientProfile(firstName: "Sally", lastName: "Sillious", group: 3),
"2345678": ClientProfile(firstName: "Sue", lastName: "Parker",group: 8),
"3456789": ClientProfile(firstName: "Bob", lastName: "Parker", group: 2),
"5678901": ClientProfile(firstName: "Jim", lastName: "Beam", group: 12)
]
// input values from scene - UITextFields
let newPhone = "4567890"
let newFirstName = "Super"
let newLastName = "Dave"
let newGroup = 14
// define struct using these input variables for values but with same keys as (global) clientDatabase
let newClientProfile = ClientProfile(firstName: newFirstName, lastName: newLastName, group: newGroup)
let newClientDatabase = [newPhone:newClientProfile]
for (phone,client) in newClientDatabase {
clientDatabase[phone] = client
}

Swift: "Cannot invoke subscript" : setting an objects members up by handing it a class's array at an index

I'm having an issue while programming in Swift. After i create an Instance of the SchedulePatientsTest class I begin to get this error: Cannot invoke 'subscript' with an argument list of type '(name:$T4, email: $T9, ssn: $T14, dob: $T19)'
Since I'm quite new to Swift I'm having trouble debugging it and googling hasn't helped much. I know it's complaining about the subscript of the array but I can't understand why. Thank you for your help!
import UIKit
struct SchedulePatientsTest {
let patientNames = [ "John Lennon", "Paul McCartney", "George Harrison", "Ringo Starr" ]
let patientEmails = [ "jlennon#beatles.com", "pmccartney#another.edu","george#something.com","drummer#beatles.org"]
let patientSSN = [ "123-45-6789","333-22-1123","567-39-9282","888-88-8888"]
let patientBirthDates = [ "05/01/1951", "06/23/1964","09/05/1955", "02/28/2001"]
let doctorNames = [ "John Smith", "Jane Doe", "Mary Jones", "Beth Garcia"]
let doctorEmails = [ "John Smith", "Jane Doe", "Mary Jones", "Beth Garcia" ]
let doctorSSN = [ "445-25-3382", "582-10-9983", "180-38-0038", "343 - 34-9875" ]
let doctorBirthDates = [ "06/03/1941", "10/10/1950", "12/25/1965", "07/19/1964" ]
let specialty = [ medicalSpecialties.GENERAL_MEDICINE, medicalSpecialties.PEDIATRICS, medicalSpecialties.GENERAL_MEDICINE, medicalSpecialties.ONCOLOGY]
init()
{
}
}
class Patient {
var name : String = ""
var email : String = ""
var ssn : String = ""
var dob : NSDate = NSDate()
init(name: String, email : String, ssn : String, dob : NSDate) {
self.name = name
self.email = email
self.ssn = ssn
self.dob = dob
}
func getName()->(String)
{
return(name)
}
}
class Doctor : Patient {
var specialty : medicalSpecialties
init(specialty: medicalSpecialties,name: String, email : String, ssn : String, dob : NSDate) {
self.specialty = specialty
super.init(name: name, email: email, ssn: ssn, dob: dob)
}
}
enum medicalSpecialties {
case GENERAL_MEDICINE
case PEDIATRICS
case ONCOLOGY
}
let CMYK = SchedulePatientsTest()
let P1 = Patient(name: CMYK.patientNames[0], email: CMYK.patientEmails[0], ssn: CMYK.patientSSN[0], dob: CMYK.patientBirthDates[0])
It's a bit of a vague error message, but the error occurs because you are passing a String instead of an NSDate to the Patient initializer.
let patientBirthDates = [ "05/01/1951", ...] creates an array of String objects, not date objects. The Patient initializer expects an NSDate for its dob parameter.
String vs NSDate
The code ["05/01/1951", "06/23/1964"] does not create an array of NSDate objects, even if the variable is defined as patientBirtDates: [NSDate]. What this is, is an array of string literals. These string literals are 'converted' into String objects. If you want to create an array of NSDate objects, you need to actually instantiate NSDate objects:
let patientBirthDates = [
NSDate(timeIntervalSince1970: 100),
NSDate(timeIntervalSince1970: 200),
NSDate(timeIntervalSince1970: 300)
]
Which method of creating NSDates you use is up to you, check the available ininitializers.