0

In mongodb, I have this doc:

{
"_id" : ObjectId("53e157918b3354f7157142d2"),
"packet" : [ 
    {
        "datetime" : ISODate("2014-08-05T16:16:46.337Z"),
        "signallingType" : "M2PA",
        "clgNum" : "",
        "cldNum" : "",
        "opc" : "6406",
        "dpc" : "327",
        "transState" : "continue",
        "otid" : "M2PA042f2ee0",
        "dtid" : "",
        "sccpCalling" : "523331461111",
        "sccpCalled" : "52333033342222",
        "imsi" : "",
        "operation" : "sendAuthenticationInfo (56)",
        "camelClgNum" : "",
        "camelCldNum" : "",
        "camelCallRefNum" : "",
        "camelImsi" : "",
        "camelEvent" : "",
        "camelReleaseCause" : "",
        "pcapFileName" : "/home/monitor/tmp/gsm_eth2_06700_20140805165712.pcap",
        "message" : "dddvid"
    }
]

}

And If I execute from the shell the following:

db.packets.update( 
{ $and: [ 
    { $or: [ 
        { "packet.otid": { $in: [ "M2PA042f2ee0" ] } },
        { "packet.dtid": { $in: [ "M2PA042f2ee0" ] } }
    ] },
    { $or: [
        { "packet.sccpCalling": { $in: [ "523331461111", "52333033342222" ] } },
        { "packet.sccpCalled": { $in: [ "523331461111", "52333033342222" ] } }
    ] }
] }, 
{ $push: { packet: { datetime: new Date(1407255406337) } } }, true 
)

The doc gets upserted without problems. Now, with c++ I do:

class Packet {

public:
    std::string packetDate;
    std::string signallingType;
    int creationTimeStamp;
    std::string clgNum;
    std::string cldNum;
    std::string opc;
    std::string dpc;
    std::string transState;
    std::string otid;
    std::string dtid;
    std::string message;
    std::string sccpCalling;
    std::string sccpCalled;
    std::string imsi;
    std::string operation;
    std::string camelClgNum;
    std::string camelCldNum;
    std::string camelCallRefNum;
    std::string camelImsi;
    std::string camelEvent;
    std::string camelReleaseCause;
    std::string pcapFile;
...

I was asked to show how I create "query_otid_or" and query_sccp_or":

mongo::BSONObj query;
mongo::BSONObj objError;
mongo::BSONObj query_otid;
mongo::BSONObj query_dtid;
mongo::BSONObj query_sccpCalling;
mongo::BSONObj query_sccpCalled;
mongo::BSONObj query_otid_or;
mongo::BSONObj query_sccp_or;
...
        tcapValuesArray.clear(); sccpValuesArray.clear();
        if( (it)->otid.length() > 0 ){
            tcapValuesArray.push_back( (it)->otid );
        }

        if( (it)->dtid.length() > 0 ){
            tcapValuesArray.push_back( (it)->dtid );
        }

        if( (it)->sccpCalling.length() > 0 ){
            sccpValuesArray.push_back( (it)->sccpCalling );
        }
        if( (it)->sccpCalled.length() > 0 ){
            sccpValuesArray.push_back( (it)->sccpCalled );
        }

        query_otid = BSON( "\"packet.otid\"" <<  BSON( "$in" << tcapValuesArray ) );
        query_dtid = BSON( "\"packet.dtid\"" <<  BSON( "$in" << tcapValuesArray ) );

        query_sccpCalling = BSON( "\"packet.sccpCalling\"" << BSON( "$in" << sccpValuesArray ) );
        query_sccpCalled = BSON( "\"packet.sccpCalled\"" << BSON( "$in" << sccpValuesArray ) );

        query_otid_or = mongo::OR( query_otid, query_dtid );
        query_sccp_or = mongo::OR( query_sccpCalling, query_sccpCalled );

...

c.update("tracer.packets",
  BSON( "$and" << BSON_ARRAY( query_otid_or << query_sccp_or ) ),
  BSON( "$push" << BSON("packet" << BSON( "datetime" << mongo::Date_t( atoll( ((it)->packetDate.substr(0,10) + (it)->packetDate.substr(11,3)).c_str() ))))), 
  true, 
  true);

It doesn't work, a new record is inserted... though it is exactly the same command...

Anybody got any ideas??

Tyler Brock
  • 29,626
  • 15
  • 79
  • 79
David Villasmil
  • 395
  • 2
  • 19
  • I would try temporarily enabling profiling level 2 to capture the query from C++: `db.setProfilingLevel(2)`. You haven't include the full C++ query code, but I'm guessing the query criteria is not generating what you expected (so the update doesn't match and always results in an insert). – Stennie Aug 06 '14 at 05:26
  • Hello @Stennie I enabled the profiling and the query is perfect. If I copy and paste into a shell mongo returns the doc.. Though in mongo logs I see the ( query: {...} update: {...} ) but i don't see the enabled upsert option anywhere, not sure if it is supposed to show in the log... – David Villasmil Aug 06 '14 at 06:39
  • If you query the `system.profile` collection, you should see this reflected as an `op:query` followed by an `op:update` if the query matches (or `op:insert` if it didn't). If you want to see in the log, increase to logLevel 1 with: `db.adminCommand( { setParameter: 1, logLevel: 1 } )`. The log line should include "upsert: true". What version of the C++ driver and MongoDB server are you using? – Stennie Aug 06 '14 at 07:11
  • @Stennie Mongodb 3.4.10, c++ Driver mongo-cxx-driver-v2.4 - I Pasted the system.profile doc here: http://pastebin.com/L8DSUUT7 Thanks a lot! – David Villasmil Aug 06 '14 at 07:36
  • Does the query document match anything in the find before doing the update? Can you boil down the example to input -> non expected result? – Tyler Brock Aug 06 '14 at 17:57
  • David, there is no mongo-cxx-driver-v2.4 unless you mean the one in the server repository itself. Is that the one you are referring to? Can you be more specific? – Tyler Brock Aug 18 '14 at 14:21

1 Answers1

1

To be clear, in your first example (through the shell) the result of running the upsert is that the document gets updated as the query is a match.

It seems to work fine for me, I think you are overquoting both "\"packet.sccpCalling\"" and "\"packet.sccpCalled\"".

#include <iostream>
#include <vector>
#include <cassert>
#include "mongo/client/dbclient.h"

using namespace std;
using namespace mongo;

int main() {
    client::initialize();

    DBClientConnection conn;
    conn.connect("localhost");
    conn.dropDatabase("test");

    BSONObjBuilder bob;
    BSONArrayBuilder bab;
    BSONObjBuilder packet;

    packet.append("otid", "M2PA042f2ee0");
    packet.append("sccpCalling", "523331461111");
    packet.append("sccpCalled", "52333033342222");

    bab.append(packet.obj());
    bob.appendArray("packet", bab.obj());
    conn.insert("test.test", bob.obj());

    vector<std::string> tcapValuesArray;
    tcapValuesArray.push_back("M2PA042f2ee0");
    vector<std::string> sccpValuesArray;
    sccpValuesArray.push_back("523331461111");
    sccpValuesArray.push_back("52333033342222");

    BSONObj query_otid = BSON( "packet.otid" <<  BSON( "$in" << tcapValuesArray ) );
    BSONObj query_sccpCalling = BSON( "packet.sccpCalling" << BSON( "$in" << sccpValuesArray ) );
    BSONObj query_sccpCalled = BSON( "packet.sccpCalled" << BSON( "$in" << sccpValuesArray ) );

    BSONObj query_otid_or = OR( query_otid, query_otid );
    BSONObj query_sccp_or = OR( query_sccpCalling, query_sccpCalled );

    BSONObj query = BSON( "$and" << BSON_ARRAY( query_otid_or << query_sccp_or ) );
    BSONObj update = BSON( "$push" << BSON("packet" << BSON( "datetime" << "updated")));

    cout << "this is the query: " << query.toString() << endl;
    conn.update("test.test", query, update, true, true);

    assert( 1 == conn.count("test.test"));
    assert( 1 == conn.count("test.test", Query("{ 'packet.datetime': 'updated' }")));
}
Tyler Brock
  • 29,626
  • 15
  • 79
  • 79