How do I prevent #<ObjectId..> to break my map with CongoMongo? - mongodb

using Clojure 1.3.0 with CongoMongo 0.1.7 and doing a simple (fetch-one :my_collection) return something like the following:
{:_id #<ObjectId 4f10d46c56bad557a7729f95>,
:key2 "value2",
:etc "etc
}
and that '#<ObjectId' breaks everything but I'm surprised I cannot find anyone with the issue anywhere.
In fact I do a simple (type *the_result_above*) I get clojure.lang.PersistentArrayMap while manually removing the # bit I correctly get clojure.lang.PersistentHashMap
Any idea? Thanks!

You are not the only one with this issue. In one of my projects I created a workaround by adding the following function:
(defn string-id [map]
(assoc map :_id (str (map :_id))))
Feed it with any map from CongoMongo, and it will replace the _id with it's string representation and return the updated map.

Related

Removing Data Type From Tuple When Printing In Scala

I currently have two maps: -
mapBuffer = Map[String, ListBuffer[(Int, String, Float)]
personalMapBuffer = Map[mapBuffer, String]
The idea of what I'm trying to do is create a list of something, and then allow a user to create a personalised list which includes a comment, so they'd have their own list of maps.
I am simply trying to print information as everything is good from the above.
To print the Key from mapBuffer, I use: -
mapBuffer.foreach(line => println(line._1))
This returns: -
Sample String 1
Sample String 2
To print the same thing from personalMapBuffer, I am using: -
personalMapBuffer.foreach(line => println(line._1.map(_._1)))
However, this returns: -
List(Sample String 1)
List(Sample String 2)
I obviously would like it to just return "Sample String" and remove the List() aspect. I'm assuming this has something to do with the .map function, although this was the only way I could find to access a tuple within a tuple. Is there a simple way to remove the data type? I was hoping for something simple like: -
line._1.map(_._1).removeDataType
But obviously no such pre-function exists. I'm very new to Scala so this might be something extremely simple (which I hope it is haha) or it could be a bit more complex. Any help would be great.
Thanks.
What you see if default List.toString behaviour. You build your own string with mkString operation :
val separator = ","
personalMapBuffer.foreach(line => println(line._1.map(_._1.mkString(separator))))
which will produce desired result of Sample String 1 or Sample String 1, Sample String 2 if there will be 2 strings.
Hope this helps!
I have found a way to get the result I was looking for, however I'm not sure if it's the best way.
The .map() method just returns a collection. You can see more info on that here:- https://www.geeksforgeeks.org/scala-map-method/
By using any sort of specific element finder at the end, I'm able to return only the element and not the data type. For example: -
line._1.map(_._1).head
As I was writing this Ivan Kurchenko replied above suggesting I use .mkString. This also works and looks a little bit better than .head in my mind.
line._1.map(_._1).mkString("")
Again, I'm not 100% if this is the most efficient way but if it is necessary for something, this way has worked for me for now.

Refine a string to only certain values scala

Is there any way to refine a string to only a certain subset of values? For example, I have a list of 500 keys in a hash map. But I only want certain keys to be inserted. For example, "abcd" and "aaaa" are valid keys but "abdc" is invalid. Is there any way to refine the String to only one of the given 500 keys?
I'm guessing the way to do this is just a very long regexp that matches abcd|aaaa?
Edit: Using the fthomas/refined library specifically the MatchesRegex function. Want to know if there is a better approach that I'm missing out on.
Scala 3 seems to Allow Singletons in Unions #6299 like so
val refinedString: "abcd" | "aaaa" = "aaaa"
whilst abdc would result in the following error
val refinedString: "abcd" | "aaaa" = "abdc"
^^^^^^
Found: String("abdc")
Required: String("abcd") | String("aaaa")
It worked for me with Dotty Scala version 0.15.0-bin-20190517-fb6667b-NIGHTLY.
I ended up actually just using generated source code that has every known key inside a MatchesRegex (a|b..) construct for 500 keys. It works. It's not pretty but it's also generated source code that I don't have to deal with so it's okay, I guess.

Clojure JDBC - This ResultSet is closed

I am currently learning using Clojure and connection with postgresql and I am stuck. In my code, I can successfully query using SELECT using java.jdbc dependency but got an exception when I UPDATE or INSERT
I am using these dependencies
[org.clojure/java.jdbc "0.7.8"]
[postgresql "9.3-1102.jdbc41"]
This is my working code for SELECT-ing from a table called public."user"
(ns knp-api.model.user
(:require [clojure.java.jdbc :as sql]))
(def db "jdbc:postgresql://ampersanda#localhost:5432/idjoesoft_klinik")
(defn get-count [q]
"Get count key from query
It takes jdbc.query as parameter"
(:count (first (into [] q))))
(defn is-user-email-available? [e]
"Returns boolean when email is available.
Take one parameter, it's email"
(let [q "SELECT COUNT(*) FROM public.\"user\" t WHERE user_email = ?"]
(sql/query db [q e] {:result-set-fn #(= 1 (get-count %))})))
and this is not my code which makes an exception appear
(defn set-user-timestamp-and-token [email token timestamp]
"update user current token and last login time inside database.
Takes email, token, and current timestamp as parameter"
(sql/update! db
"public.\"user\""
{:user_last_login (str "to_timestamp(" timestamp ")")
:user_token token}
["user_email = ?" email]))
and this is the exception
UPDATE
I also try using REPL to create table and I also get the same results.
knp-api.handler=> (require '[clojure.java.jdbc :as sql])
nil
knp-api.handler=> (sql/db-do-commands "jdbc:postgresql://ampersanda#localhost:5432/idjoesoft_klinik" (sql/create-table-ddl :testing [[:data :text]]))
PSQLException This ResultSet is closed. org.postgresql.jdbc2.AbstractJdbc2ResultSet.checkClosed (AbstractJdbc2ResultSet.java:2852)
I suspect the update is happening fine, and then it's trying to return the rows that changed, and it's trying to do so as a lazy sequence. the thing that tries to print/process that lazy sequence of results may be doing so after the connection is closed.
try wrapping the select statement in a call to doall to ensure that it's read immediately and not allowed to be a lazy database.
Having run into the same issue today, the root cause is the postgresql java driver.
postgresql "9.3-1102.jdbc41" is five years old, after upgrading to 42.2.6 the issue went away.
I remember having this problem, but it's many years ago and I can't remember the solution. However, wrapping raw JDBC in Clojure is not a good idea. There are a number of excellent Clojure libraries which make working with databases much easier. I'd particularly recomment SQL Korma and Hug SQL.
Having spent a while trying to get this solved I can confirm in my case updating the postgresql java driver solved this issue, if anybody is having the same issue try to use the newest driver from clojars/maven, Clojars even has a message telling you that you should use the version from maven central.

How to convert "like each" into a functional form?

Let's say I have a column of a table whose data type is a character array. I want to pass in a functional select where clause, where the column is in a list of given strings. However, I cannot simply use (in; `col; myList) for reasons. Instead, I need to do the equivalent of:
max col like/: myList
which effectively gives the same result. However, I have tried to put this in functional form
(max; (like/:; `col; myList))
And I am getting a type error. Any ideas on how I could make this work?
A nice trick when dealing with this problem is using parse on a string of the select statement you want to functionalize. For example:
q)parse"select from t where max col like/: myList"
?
`t
,,(max;((/:;like);`col;`myList))
0b
()
Or specifically in your case you want the 3rd element of the result list (the where clause):
q)(parse"select from t where max col like/: myList")2
max ((/:;like);`col;`myList)
I even think using this pattern in your actual code can be a good idea, as functionalized statements like max ((/:;like);`col;`myList) can get pretty unreadable pretty quickly!
Hope that helps!
(any; ((/:;like); `col; enlist,myList))
it should be: (max;((/:;like);`col;`mylist))

How do you unwrap the metadata from a ClojureScript object?

Adding meta data to an object returns a new object with the metadata attached:
(def plain-data [1 2 3])
(def decorated-data (with-meta plain-data {:url "http://stackoverflow.com"}))
;; returns false
(identical? plain-data decorated-data)
How do I recover the original plain-data from the decorated-data?
I'd like to do something like,
(def undecorated-data (with-meta decorated-data nil))
;; how can I make this return true?
(identical? plain-data undecorated-data)
Adding metadata doesn't wrap the value, it returns a clone of the value with metadata attached - there's no way to recover the original thing. However it's not clear why you would ever need to do that, use = if you need to check for equality.