How to convert a MongoDB RawDocumentBuf to a Rust struct? - mongodb

I am trying to use MongoDB rust driver with Rayon to make it faster.
I know how to convert a RawDocumentBuf into a Document like this, which works really fast.
let docs: Vec<RawDocumentBuf> = coll.find(None, None).await?.try_collect::<Vec<_>>().await?;
let _y: Vec<Document> = docs.par_iter().map(|x| x.to_document().unwrap()).collect();
But I want a Rust struct, say Book, eventually.
A Document can be converted into a struct, but I am not sure how to get a struct in the closure above.
let book: Book = bson::from_bson(Bson::Document(doc));

You just missed another unwrap() after from_bson() at the end.
However you don't have to go via Document, you can deserialize from a RawDocumentBuf via bson::from_slice():
let docs: Vec<RawDocumentBuf> = coll.find(None, None).await?.try_collect().await?;
let books: Vec<Book> = docs
.par_iter()
.map(|raw| bson::from_slice(raw.as_bytes()).unwrap())
.collect();

Related

Swift - How to map an array of objects with an function on the object

I have an array of documents and want to use the toModel function on the document to transform all elements.
let documents = docs.map { $0.toModel() }
toModel() transforms the struct into another struct.
Is there a nicer, easier or more elegant way to do this?
I thought about something like let documents = docs.map(\.toModel)
Use a Model initializer that takes whatever a doc is as its argument. “to” methods are not Swifty because initializers are so versatile.
let documents = docs.map(Model.init)

I want to store formatted text in Realm Swift database

noob swift guy here.
I have this UITextView where the user writes something. I need to store his "note" to the database with all the formated text in it. That means if it has bold, I need to display it as bold later.
This text should be stored in local Realm Swift Database. Any solutions how can I achieve that? I head about "Markdown", but I didn't understand how can that be useful.
Much thanks! Have a great day!
Realm only stores ascii text and cannot directly store any formatting properties like BOLD, and that's true for most databases.
If you want to store formatted strings, one option is to archive it to a Data type, which Realm fully supports. Then, when reading data back in, unarchive it from Data back to a formatted string. (formatted strings are often called Rich Text or in code: attributedStrings)
The below code is macOS but iOS will be similar
A quick example - here's a class to hold a some attributed string data
class MyAttrStringClass: Object {
#Persisted var attrStringData: Data!
}
Suppose we have a (rich) text field with the following text
Hello, World
To store the class with the attributed string in Realm:
let s = self.myRichTextField.attributedStringValue
let data = try! NSKeyedArchiver.archivedData(withRootObject: s, requiringSecureCoding: false)
let myObject = MyAttrStringClass()
myObject.attrStringData = data
try! realm.write {
realm.add(myObject)
}
then when reading back from Realm and displaying the attributed string in that same field
let myObject = realm.objects(MyAttrStringClass.self).first!
let data = myObject.attrStringData!
let s = try! NSKeyedUnarchiver.unarchivedObject(ofClass: NSAttributedString.self, from: data)
self.myRichTextField.attributedStringValue = s!
Note: there's no error checking in the above. Please protect your code by safely unwrapping optionals.

Convert an array of dictionaries into a set Swift 4

I have an array of dictionaries ([[Double:Double]]) which I want to convert into a Set of dictionaries. My goal is to use the .symmetricDifference to find the differences between two arrays (both are of type [[Double:Double]]). How can I do this?
I found this on hackingwithswift.com and tried to use it but I am getting this error:
Type '[[Double : Double]]' does not conform to protocol 'Hashable'
I have also tried this code...
let array1:[[Double:Double]] = [[4.5:3.678], [6.7:9.2867], [7.3: 8.7564]]
let array2:[[Double:Double]] = [[4.5:3.678], [6.7:9.2867]]
let array3 = Set<[[Double:Double]]>(array1).symmetricDifference(Set(array2)) //On this line I get the error above.
You don't want a Set of [[Double:Double]]. You want a Set of [Double:Double], because those are the objects in the array and you want them to be the objects in the Set.
Thus the right thing will happen if you simply say
let array1:[[Double:Double]] = [[4.5:3.678], [6.7:9.2867], [7.3: 8.7564]]
let set1 = Set(array1)
and so on.
This might require you to update to a newer version of Swift. It works in Swift 4.2.

Retrieving NSOrderedSet from Core Data and casting it to entity managedObjectSubclasss

Im making a Fitness app to learn Core data, and I have found that I need to let the user store every performed workout as a WorkoutLog item, and in there, there should be a series of ExerciseLogs which represents performances of that exercise (it contains each lift and also a reference to the actual exercise design).
Problem is that after a while i realize that i need to have these ordered, so that the next time i want to show the user their workout, the order that the exercisese were performed should be the same.
So I checked "ordered" in the top right of the image there, and now my code is in dire need of an update. I have tried to read as much as I could about working with NSOrderedSet and how to fetch them from core data and then manipulate them, but I havent really found much of use to me. (I have no experice in objective-c)
For example my code that used to be:
static func deleteWorkoutLog(_ workoutLogToDelete: WorkoutLog) {
guard let exerciseLogsToDelete = workoutLogToDelete.loggedExercises as? Set<ExerciseLog> else {
print("error unwrapping logged exercises in deleteWorkoutLog")
return
}
I get the error: .../DatabaseFacade.swift:84:77: Cast from 'NSOrderedSet?' to unrelated type 'Set' always fails
So what ive learned about sets and core data no longer seems applicable.
Im far from an expert in programming, but im very eager to learn how to get access to the loggedExercises instances.
TLDR; Is there a way to cast NSOrderedSet to something I can work with? How do we usually work with NSManagedSets from core data? Do we cast them to Arrays or MutableSets? I would very much appreciate an example or two on how to get started with retrieving and using these ordered sets!
Thanks
For anyone else wondering how to get started with orderedSets in core data:
After setting my the WorkoutLog.loggedExercises "to-many" relationship to be ordered, I managed to access them through the mutableOrderedSetValue function like this:
static func deleteWorkoutLog(_ workoutLogToDelete: WorkoutLog) {
let orderedExerciseLogs: NSMutableOrderedSet = workoutLogToDelete.mutableOrderedSetValue(forKey: "loggedExercises")
let exerciseLogsToDelete = orderedExerciseLogs.array
for exerciseLog in exerciseLogsToDelete {
guard let exerciseLog = exerciseLog as? ExerciseLog else {
return
}
Works great so far.
And to rearrange the NSOrderedSet I ended up doing something like this:
// Swap the order of the orderedSet
if let orderedExerciseLogs: NSOrderedSet = dataSourceWorkoutLog.loggedExercises {
var exerciseLogsAsArray = orderedExerciseLogs.array as! [ExerciseLog]
let temp = exerciseLogsAsArray[indexA]
exerciseLogsAsArray[indexA] = exerciseLogsAsArray[indexB]
exerciseLogsAsArray[indexB] = temp
let exerciseLogsAsOrderedeSet = NSOrderedSet(array: exerciseLogsAsArray)
dataSourceWorkoutLog.loggedExercises = exerciseLogsAsOrderedeSet
}

Realm Swift Results get object at index

I couldn't find this anywhere so I thought I'd ask here.
I'm using Realm in Swift and I'm having trouble to get an object out of the Results at a certain index. I'm using it inside my UITableViewController. I'm making a var at the beginning of the class:
var tasks:Results<Task>?
And then to get it I .objects(type: T.Type):
tasks = realm.objects(Task)
I was hoping to be able to do something like this:
let task = tasks!.objectAtIndex(1)
Is this a limitation or is there another way to do this?
Use standard indexing syntax to retrieve the value:
let task = tasks![1]
Since tasks is an optional, it could be nil. A safer way to write this would be to use optional binding with optional chaining:
if let task = tasks?[1] {
// use task
}