globalsign / mgo

The MongoDB driver for Go
Other
1.97k stars 231 forks source link

Upsert treats string as array on complex indexes #307

Closed toxicafunk closed 5 years ago

toxicafunk commented 5 years ago

What version of MongoDB are you using (mongod --version)?

db version v4.0.2
git version: fc1573ba18aee42f97a3bb13b67af7d837826b47
OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016
allocator: tcmalloc
modules: none
build environment:
    distmod: ubuntu1604
    distarch: x86_64
    target_arch: x86_64

What version of Go are you using (go version)?

go version go1.11.2 linux/amd64

What operating system and processor architecture are you using (go env)?

manjaro linux amd64

What did you do?

Given the following collection and index

db.createCollection("events");
db.events.createIndex(
    {
        "profileid": 1.0,
        "createdat": 1.0,
        "sessionid": 1.0,
        "eventid": 1.0
    }, {"unique": true});

When trying to insert 2 documents with same profileid, createdat and sessionid BUT different eventid, eventid is ignored from the index query so instead of creating a new document the previous one s updated. See attached test for the struct and code.

Debugging mongo I can see that eventid is being treated as an Array:

---------bounds = field #0['profileid']: ["gk40zv0tngn0nik8zh85sb148qs87sinkk1egtr1", "gk40zv0tn
       │ gn0nik8zh85sb148qs87sinkk1egtr1"], field #1['createdat']: [new Date(1543490864137), new Date(154
       │ 3490864137)], field #2['sessionid']: ["uan0h0vyk1hpxwt7udhl", "uan0h0vyk1hpxwt7udhl"], field #3[
       │ 'eventid']: [MinKey, MaxKey]

Insert and Bulk work as expected as can be determined from the test.

mongodb_test.txt

eminano commented 5 years ago

Hi @toxicafunk,

Looking at the description of what upsert does:

// Upsert finds a single document matching the provided selector document
// and modifies it according to the update document.  If no document matching
// the selector is found, the update document is applied to the selector
// document and the result is inserted in the collection.
// If the session is in safe mode (see SetSafe) details of the executed
// operation are returned in info, or an error of type *LastError when
// some problem is detected.

The selector you're using in your upsert test doesn't use the eventid, so the behaviour you're experiencing is expected. You can have a look at some of the upsert examples in the tests for understanding the usage.

Thanks, Esther

toxicafunk commented 5 years ago

Thanks @eminano,

Can confirm I messed up the selector and it actually works correctly. Thanks for your time.