I am looking for some help with this. I am following the example for nimongo from https://github.com/SSPkrolik/nimongo
In the code segment below I have changed the example to read a json file using parsejson to pass it on to mongo insert like this:
## Testing connection establishing result
echo "Async connection established: ", connected
## Inserting multiple documents into MongoDB
let
doc3 = parseJson("/home/gt/tmp/tmp2/hfile.json")
let a = waitFor(collection.insert(doc3))
echo doc3
However there is type mismatch in what parsejason puts in doc3 variable for mongo insert. Any ideas how I the best way to the fix the type mismatch here?
The error return the compiler is as follows:
basic_4_work.nim(24, 10) Error: ambiguous call; both json.%*(x: untyped)[declared in lib/pure/json.nim(844, 6)] and bson.%*(x: expr)[declared in /home/gt/.nimble/pkgs/nimongo-0.1/nimongo/bson.nim(498, 6)] match for: ()
The content of the json file is validated using json lint, and it looks like this:
{
"v_id": 343456,
"v_date": "02-01-2018",
"v_tag": "42_matt_02-01-2018",
"origin": "mt_x11_42",
"author": "matt mattingly",
"descr": "matts_test_cases"
}
It's conflict between json.%* and bson.%* .
To avoid it you can use toBson manually like example below. (I didn't test this)
e.g.
import json
let jsonobj = parseJson"""{
"v_id": 343456,
"v_date": "02-01-2018",
"v_tag": "42_matt_02-01-2018",
"origin": "mt_x11_42",
"author": "matt mattingly",
"descr": "matts_test_cases"
}"""
proc toBson(jobj: JsonNode): Bson =
result = B()
for k, v in jobj:
result[k] = v.toBson
var doc = jsonobj.toBson
Just use bson.`%*`(...) instead of %*(...) or:
import json except `%*`
I suspect a pair of procedures that converts generically from json-to-bson and vice versa is a good idea for the library. I've got a PR on that library I'm already working on and might add it. But I do, it will not be part of the main code: it would be a sub-module ( such as import nimongo/jsonbson)
@mashinggan I will probably use your code for a start. I'll also add mongodb-specific extras that helps with the conversion from JSON. Such as JSON
{
"some_id": { "$oid": "29384239bc323..." }
}
becoming BSON:
{
"some_id": oid("29384239bc323...")
}
Also, if curious, I'm working on a Object-Document-Model (ODM) library that sits on nimongo called objectmongo. It is VERY alpha. But you are welcome to play with it. It would allow you to do this:
import
objectmongo,
json
m = connect_mongodb()
type
HRef = object of MongoCollection:
v_id: int
v_date: datetime
v_tag: string
origin: string
author: string
descr: string
wrap_collection(HRef)
var doc = parseFile("/home/gt/tmp/tmp2/hfile.json").to(HRef)
discard doc.save(m)
@mashingan, May I ask -- What is the right way to read back all the "jsonobj" data from mongodb after having done many inserts in my original question. I am trying variants of the following but having no success so far. Thanks again.
let documents = collection.find(%*{})
@dom96 In my experience, it couldn't be solved simply like that, but at the time the error message was so strange I didn't even sure what to ask. Checked the implementation and bson.%* actually using toBson hence I used toBson directly.
@JohnAD yeah, go ahead use it. I usually use some write some codes just to solve what I wanted so not sure whether on how to put it as library. I'll try your lib as soon I've to work with mongodb again.
@luvnim I'm not sure the correct way, but you can do the reverse of toBson do. e.g.
import nimongo/bson, nimongo/mongo, json, times, strformat
proc toJson(doc: Bson): JsonNode =
case doc.kind
of BsonKindDouble: result = doc.toFloat64.newJFloat
of BsonKindInt32, BsonKindInt64: result = doc.toInt.newJInt
of BsonKindBool: result = doc.toBool.newJBool
of BsonKindTimeUTC: result = doc.toTime.`$`.newJString
of BsonKindStringUTF8: result = doc.toString.newJString
else:
raise newException(NimongoError, fmt"Invalid bson kind type got {doc.kind}")
Please note the snippet above is not exhaustedly checking the BsonKind enum. I leave it the rest as excercise for you :P