SSPkrolik / nimongo

Pure Nim lang MongoDB driver
http://sspkrolik.github.io/nimongo
MIT License
101 stars 20 forks source link

needs documentation in README: insert(bson) modifies bson; re-inserting will have no effect #67

Open timotheecour opened 5 years ago

timotheecour commented 5 years ago

this generates a single insert:

import std/[
  oids,
  asyncdispatch,
]
import nimongo/bson
import nimongo/mongo

proc test_sync2=
  var m = newMongo()
  doAssert m.connect()
  let mc = m["tmp"]["tnimongo"]

  let doc = %*{
    "name": "bob4",
  }

  for i in 0..<2:
    # doc["number"] = toBson i
    # echo doc
    let ai = mc.insert(doc)
    echo ai
    doAssert ai

test_sync2()

the equivalent code in D generates 2 inserts:

/+dub.sdl:
dependency "vibe-d" version="~>0.8.0"
+/

/+
[[critical] mongo errors silently ignored · Issue #66 · SSPkrolik/nimongo](https://github.com/SSPkrolik/nimongo/issues/66)
+/

import vibe.data.bson;
import vibe.db.mongo.mongo;
import std.stdio;

void main(){
  auto name = "case2";
  test(name);
}

void test(string name)
{
  MongoClient client = connectMongoDB("127.0.0.1");
  MongoCollection users = client.getCollection("tmp.tnimongo");
  if(name == "case2"){
    auto a = Bson(["name": "bob3".Bson]);
    users.insert(a);
    users.insert(a);
  }
}

likewise with other clients, eg the mongo shell client

foo={name:"bob5"}
db.tnimongo.insert(foo)
db.tnimongo.insert(foo)
db.tnimongo.count()
2

edit

in python, it behaves same as Nim (well almost, minus the fact that python will throw, see https://github.com/SSPkrolik/nimongo/issues/66)

import pymongo
from pymongo import MongoClient
client = MongoClient()
cm = client.tmp.tnimongo
obj = {"name": "bob6"}
for i in range(2):
  print(obj)
  ret = cm.insert_one(obj)
  print(obj)
  print(ret.inserted_id)

maybe behavior of Nim is ok, and derives from fact that Bson is a reference type (unlike Bson in Nim); this could have advantages in terms of efficiency (avoiding copies), but IMO should be clearly documented in README that insert modifies input Bson (unlike other implementations, eg D, mongo shell)

workaround

pending https://github.com/nim-lang/Nim/pull/9740 we can do:

let ai = mc.insert(doc.deepCopy)