Issue Updating a field that doesn't exist in MongoDB using F# - mongodb

I have written a save function
let saveRecord(record: PostDataItem, coll: IMongoCollection<PostDataItem>, orderNumberToCheck: string) =
let filterDefinition = Builders<PostDataItem>.Filter.Eq((fun d -> d._id), record._id)
let update = Builders<PostDataItem>.Update.Set((fun f -> f.orderNumberToCheck),orderNumberToCheck)
let options = new UpdateOptions(IsUpsert=true)
let result = coll.UpdateOne(filterDefinition, update, options)
result
Unfortunately the result from MongoDB tells me that it found a match when trying to update, but it did not modify it ( matched=1, modified=0 ). The only unique thing about this is that the field "orderNumberToCheck" doesn't actually exist prior to this - but I assumed that upsert would take care of that. My type is below.
[<CLIMutable>]
type PostDataItem = {
_id: BsonObjectId
dateLodged: DateTime
productCode: string
productDescription: string
clientReference: string
manifestContract: string
client: string
quantity: string
unitPrice: string
gst: string
total: string
clientReference2: string
weight: string
reference1: string
ticketNumber: string
transactioncode: string
invoiceExplanationField1: string
invoiceExplanationField2: string
invoiceExplanationField3: string
invoiceExplanationField4: string
invoiceExplanationField5: string
invoiceExplanationField6: string
[<BsonDefaultValue(null)>]
orderNumberToCheck: string
[<BsonDefaultValue(null)>]
isUnique: Nullable<bool>
[<BsonDefaultValue(null)>]
expectedPrice: Nullable<decimal>
}

Related

Covert ObjectId to String SwiftUI Realm object

I have my model called Restaurant:
realm object on kotlin:
class Restaurant : RealmObject {
#PrimaryKey
var _id: ObjectId = ObjectId.create()
var name: String = ""
var adress: String? = null
}
I want to use the _id property. But for that I need to convert to a String in SwiftUI
I tried: restaurant_id as! String, it does not work,
Is is related to this post: https://www.mongodb.com/community/forums/t/swift-convert-objectid-to-string/121829
No real answers there
Any other solutions?
the error when using .toHexString(): Value of type 'any Library_baseObjectId' has no member 'toHexString':
the type of _id in this case:
The error when trying: "\(restaurant._id.stringValue)"
I solved this by adding a getter to the class:
class Restaurant : RealmObject {
#PrimaryKey
var _id: ObjectId = ObjectId.create()
var name: String = ""
var adress: String? = null
fun getID() : String{
return _id.toString()
}
}
ObjectID's in Swift have a stringvalue property which returns the ObjectID as a string
You could do this
let idAsAsString = someRealmObject._id.stringValue
Or for kotlin and other SDK;s
let idAsString = object._id.toString()
In SwiftUI, the id can be accessed in a similar way, and then use the value to init a new string
let x = someRealmObject._id.stringValue
let y = String(stringLiteral: x)
let _ = print(x, y)
Text("\(x) \(y)")
and the output will be
6376886a1dbb3c142318771c 6376886a1dbb3c142318771c
in the console and the same in the Text in the UI
Here's some SwiftUI showing the use
List {
ForEach(myModel) { model in
NavigationLink(destination: SecondView(navigationViewIsActive: $navigationViewIsActive, selectedEntryToShow: model))
{
Text("\(model._id.stringValue)") //ormodel._id.toString()
}
}
}
This Swift model works perfectly and the string of ObjectId can be read per above.
class Restaurant: Object {
#Persisted(primaryKey: true) var _id: ObjectId
#Persisted var name: String = ""
#Persisted var adress: String? = null
}

How to get the data from mongodb with all the struct variables?

In this code, I am trying to access the Cardname from the MongoDB database but it is giving me an empty string. Although it prints all the variables before Cardname but does not print the variables after Cardname and Cardname itself.
type UserCredentials struct {
Fname string
Lname string
Email string
Password string
Phone string
Country string
State string
Faddress string
Laddress string
Postal string
Company string
Cardname string
Cardnumber string
Expmonth string
Expyear string
}
func FindCard(email, password string) {
var uc UserCredentials
collection := Connect.Database("eCommerce").Collection("register")
if err := collection.FindOne(context.TODO(), bson.M{"email": email, "password": password}).Decode(&uc); err != nil {
log.Fatal(err)
}
fmt.Println(uc.Cardname)
}
The mongo driver will not magically find out which document field you want to set into which struct field.
There are some "common sense" rules, such as field names matching properties (even if the first letter is not capitalized), but the field name Cardname will not be matched with the property name "card name".
You have to tell the mapping using struct tags, namely the bson struct tag (this is what the mongo-go driver uses).
For example:
type UserCredentials struct {
Fname string
Lname string
Email string
Password string
Phone string
Country string
State string
Faddress string
Laddress string
Postal string
Company string
Cardname string `bson:"card name"`
Cardnumber string `bson:"card number"`
Expmonth string `bson:"expiry month"`
Expyear string `bson:"expiry year"`
}

Swift: Prepend String character when setting an Int variable

I've looked across Google and have found no answer to the below..
I'm looking to prepend a single String character to a list of numbers: A12345
In the example below I'm creating the class and when declaring an instance, setting the employeeNumber to 12345. Later on, when the property is called, I'd like it to return employeeNumber prepend with the letter p.
class Employee {
var surname: String
let forename: String
let employeeNumber: Int {
set {
"p\(employeeNumber)"
}
}
}
let employeeOne = Employee(surname: "Jones", forename: "Tom", employeeNumber: 12345)
employeeOne.employeeNumber // returns A12345
I appreciate that this code might be WELL off what I should be using (i.e using a setter?).
What you are looking for is a function (or a computed property) that returns a String value made of the employee number prefixed by a letter:
struct Employee {
var surname: String
var forename: String
var employeeNumber: Int
var employeeNumberAsString: String {
"A\(employeeNumber)"
}
}
let employee = Employee(surname: "Jones", forename: "Tom", employeeNumber: 12345)
print(employee.employeeNumberAsString)
// prints "A12345"
Your employee number is an Int, you can't set it with a String, use a property that stores the number and a function to retrieve the formatted number.

Update only by payload

I am making rest API using go and echo, and I'm working on updating data. At first I was using struct to store the payload and then do the update to mongodb
type updatePayload struct {
FullName string `json:"fullName" bson:"fullName"`
FirstName string `json:"firstName" bson:"firstName"`
LastName string `json:"lastName" bson:"lastName"`
Location string `json:"location" bson:"location"`
Gender string `json:"gender" bson:"gender"`
State string `json:"state" bson:"state"`
Subdistrict string `json:"subdistrict" bson:"subdistrict"`
Address string `json:"homeAddress" bson:"homeAddress"`
Profession string `json:"provession" bson:"provession"`
Settings struct {
Email bool `json:"email" bson:"email"`
SMS bool `json:"sms" bson:"sms"`
GCM bool `json:"gcm" bson:"gcm"`
} `json:"settings" bson:"settings"`
Coordinates struct {
Type string `json:"type" bson:"type"`
Coordinates []float64 `json:"coordinates" bson:"coordinates"`
} `json:"coordinates" bson:"coordinates"`
}
The update is working but if I'm not send all the parameters like only send one field , the rest of the fields is updated to, only it was an empty string ""
is there any way I can only update the field that was specified on the request payload.
You have to specify omitempty on the struct
type PayloadUpdateProfile struct {
FullName string `json:"fullName,omitempty" bson:"fullName,omitempty"`
FirstName string `json:"firstName,omitempty" bson:"firstName,omitempty"`
LastName string `json:"lastName,omitempty" bson:"lastName,omitempty"`
}
Bind the payload into the struct as usual
var payload profile.PayloadUpdateProfile
err := c.Bind(&payload)
then convert it
var payloadInterface map[string]interface{}
inrecPayload, _ := json.Marshal(payload)
json.Unmarshal(inrec, &payloadInterface)
UpdateMethod(ctx, filter, payloadInterface)
You can do things like this:
type updatePayload struct {
FullName string `json:"fullName" bson:"fullName"`
FirstName string `json:"firstName" bson:"firstName"`
LastName string `json:"lastName" bson:"lastName"`
Location string `json:"location" bson:"location"`
Gender string `json:"gender" bson:"gender"`
State string `json:"state" bson:"state"`
Subdistrict string `json:"subdistrict" bson:"subdistrict"`
Address string `json:"homeAddress" bson:"homeAddress"`
Profession string `json:"provession" bson:"provession"`
Settings struct {
Email bool `json:"email" bson:"email"`
SMS bool `json:"sms" bson:"sms"`
GCM bool `json:"gcm" bson:"gcm"`
} `json:"settings" bson:"settings"`
Coordinates struct {
Type string `json:"type" bson:"type"`
Coordinates []float64 `json:"coordinates" bson:"coordinates"`
} `json:"coordinates" bson:"coordinates"`
}
func (payload *updatePayload) prepareUpdateQuery() (bson.M, error) {
updateQuery := make(bson.M)
if len(payload.FirstName) != 0 {
updateQuery["firstName"] = payload.FirstName
}
if len(payload.LastName) != 0 {
updateQuery["lastName"] = payload.LastName
}
// do same like above for other fields
updateQ := make(bson.M)
updateQ["$set"] = updateQuery
return updateQ, nil
}
have the method on updatePayload struct and after decoding the api payload , call this method and generate the update query for those fields only which has data from api payload. Once update query is made pass that update query to mongodb update wrapper function .

Want to create particular property value array from array

Having array of employee object, called employees and now I want to create another array called filteremployees which is having only id and date of birth value.
Using
let filteremployees = employee.map({ $0.id})
I can get array which contains only id value but i want to have id as well dateOfBirth
class Employee {
var id: Int
var firstName: String
var lastName: String
var dateOfBirth: NSDate?
init(id: Int, firstName: String, lastName: String) {
self.id = id
self.firstName = firstName
self.lastName = lastName
}
}
Try this:
let employees : [Employee] = ...
let list: [(Int, NSDate?)] = employees.map { ($0.id, $0.dateOfBirth) }
You must explicitly declare the type of list otherwise you get this error from the compiler
Type of expression is ambiguous without more context.
Tested with Xcode 7 Playground and Swift 2.0.
Hope this helps.
You could try using the same map method and returning a tuple of your expected values:
let filter employees: [(Int, NSDate?)] = employee.map({ ($0.id, $0.dateOfBirth) })
Alternatively, and I think this is a better solution, create a new value type and create that with only your required values
struct FilteredEmployee {
let id: String
let dateOfBirth: NSDate?
init(employee: Employee) {
id = employee.id
dateOfBirth = employee.dateOfBirth
}
}
And then you can map the initialiser over the array
let filteremployees = employee.map { FilteredEmployee($0) }