Avoid duplication when serializing/deserializing mongodb documents - mongodb

I have 2 collections:
profiles
dances
struct Profile {
id: String,
firstname: String,
dances: Vec<String>
}
struct DanceModel {
id: String,
name: String,
}
I have a find query which does a lookup on the dances collection.
let cursor = profile_collection.aggregate(pipeline, None).await.unwrap();
let results = cursor.try_collect().await.unwrap_or_else(|_| vec![]);
let profile = results.first().unwrap();
let result = bson::from_document::<ProfileResult>(profile.clone());
I created a new model like so:
struct ProfileResult {
id: String,
name: String,
dances: Vec<DanceModel>
}
As you can see, the id and name fields are being duplicated, and I have 2 models for the same data.
Is there any way to avoid duplication of attributes and data models?

It looks like you are trying to apply an object concept to a procedural technology.
To work around this issue, you can create an IdName struct and apply that struct to the model in a uid field.
struct IdName {
id: String,
name: String,
}
struct Profile {
id: String,
firstname: String,
dances: Vec<String>
}
struct DanceModel {
uid: IdName
}
struct ProfileResult {
uid: IdName
dances: Vec<DanceModel>
}

Related

How can I be able to access the label and value of a constant/variable in Swift?

I am using Mirror to access the children of my struct like this:
struct TestType {
var firstName: String
var lastName: String
var value: String {
return firstName + lastName
}
}
use case:
let person: TestType = TestType(firstName: "Tim", lastName: "Cook")
for property in Mirror(reflecting: person).children {
print("label: \(property.label!)", "value: \(property.value)")
}
results:
label: firstName value: Tim
label: lastName value: Cook
Now my goal is do the same thing for the person constant as well, with that said, I want be able to access the label of person which is person and the value of it, the result should look like this:
label: person value: Tim Cook
How can i do this in Swift?
Honestly I have no idea why need to use Mirror here) would be great if you would describe it in as a comment below this answer. I would appreciate it)
but the reason why you can't what you need is because of Mirror can't see computed properties, as far as I know. Any way you can customise your init method to reach what you need. But remember that using Mirror is too expensive, for example: if it in inherited object it will parse every single thing in parent classes which could be accessible for Mirror
struct TestType {
let firstName: String
let lastName: String
let person: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
person = [firstName, lastName].joined(separator: " ")
}
}

How can i get a specific element of a collection with specific id in SwiftUI?

I have a function where i pass a collection (reversed) of Messages with an ID. How can i get the specific message corresponding to this ID?
My Struct :
import Foundation
import FirebaseFirestoreSwift
struct Message_M: Codable, Identifiable, Hashable {
#DocumentID var id: String?
var msg: String
var dateCreated: Date
var userFrom: String
...
enum CodingKeys: String, CodingKey {
case id
case msg
case dateCreated
case userFrom
...
}
}
I want to do something like this... messages(#DocumentID: ID).userFrom is not working here and i don't know how to get the correct syntax.
func checkRead(from: String, messages: ReversedCollection<[Message_M]>, ID: String) {
if currentUserID != messages(#DocumentID: ID).userFrom {
// Do something here...
}
}
Here is a way for you:
func checkRead(from: String, messages: ReversedCollection<[Message_M]>, ID: String) {
if let message: Message_M = messages.first(where: { element in element.id == ID }) {
print(message.msg)
}
}

Using models with sub models in CoreData

I am trying to implement a cache using CoreData.
Up until this point I've been storing models that are simple, however I have a model below that contains data types such as CodablePartialUser and CodableFeedItemType.
How should these types be modelled in CoreData?
Should I use the Data type and store them in a data format?
As CodableFeedItemType is an enum, should I store the raw value and convert between formats again?
struct CodablePartialUser: Equatable, Codable {
let userID: String
let firstName: String
let lastName: String
init(userID: String, firstName: String, lastName: String) {
self.userID = userID
self.firstName = firstName
self.lastName = lastName
}
}
enum CodableFeedItemType: String, Codable {
case recognition = "RECOGNITION"
case news = "COMPANY_NEWS"
}
struct CodableFeedItem: Codable {
let id: String
let type: CodableFeedItemType
let createdDate: Date
let createdBy: CodablePartialUser
let likesCount: Int
let commentsCount: Int
let externalID: String
let title: String?
let imageURL: URL?
init(id: String, type: CodableFeedItemType, createdDate: Date, createdBy: CodablePartialUser, likesCount: Int, commentsCount: Int, externalID: String, title: String?, imageURL: URL?) {
self.id = id
self.type = type
self.createdDate = createdDate
self.createdBy = createdBy
self.likesCount = likesCount
self.commentsCount = commentsCount
self.externalID = externalID
self.title = title
self.imageURL = imageURL
}
}
For the CodablePartialUser you can use relationship by creating a new Entity named as "CodablePartialUser"
For CodableFeedItemType you can use enum as like
enum CodableFeedItemType: String, Codable {
case recognition = "RECOGNITION"
case news = "COMPANY_NEWS"
}
extension CodableFeedItemEntity {
var type: CodableFeedItemType {
get {
return CodableFeedItemType(rawValue: typeRaw)!
}
set {
typeRaw = newValue.rawValue
}
}
}

Return partial object in Vapor 3

I would like to return a partial object in a response for another object type.
For example, I have a UserProfile model:
var id: Int?
var email: String
var firstName: String?
var lastName: String?
and an Adult model:
var id: Int?
var nickname: String
var type: String
var user: User.UserProfile
var family: Family
Say I would like to return just the UserProfile's email address in the Adult response, what is the way to go about that?
I have tried an approach with child/parent relationships, where my Adult model is more like:
var id: Int?
var nickname: String
var type: String
var user: User.ID
var family: Family
..but then my response just contains an object ID, but I really want to return a partial (or even full in some cases) object.
Thanks in advance.
The way this is done is to create a 'public' definition of your model, which will represent the JSON you return from your route.
For your model, you might create a struct like this:
struct AdultResponse: Content {
var id: Int?
var nickname: String
var type: String
var email: String
var family: Family
init(adult: Adult) {
self.id = adult.id
self.nickname = adult.nickname
self.type = adult.type
self.email = adult.user.email
self.family = adult.family
}
}
You can then get your Adult model from the database, create an AdultResponse and return that from your route.

How to use a slug in Vapor 3

How would I go about generating a slug for a SQLiteModel object, and using it in Leaf for Vapor 3? My goal is to provide a search engine friendly link to the detail page of my model (for example, /tag/swift/ vs. /tag/0/), rather than link using the id.
I found the Parameter protocol, which means my model has a uniqueSlug property. Unfortunately using it in Leaf #(model.uniqueSlug) doesn't work.
Here's my leaf code:
#for(tag in tags) {
<a class="tag" href="tag/#(tag.id)">#(tag.name)</a>
}
Here's my model:
final class Tag: SQLiteModel, Codable {
var id: Int?
var name: String
var description: String
init(id: Int? = nil, name: String, description: String) {
self.id = id
self.name = name
self.description = description
}
}
extension Tag: Migration { }
extension Tag: Content { }
extension Tag: Parameter { }
I also tried adding a computed property to the model:
var slug: String {
return "test"
}
That also doesn't work.