В mongodb у меня есть этот документ:
{
"_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"}
]
}
И если я выполню из оболочки следующее:
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
)
Док расстроен без проблем.
Теперь с C ++ я делаю:
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;
...
Меня попросили показать, как я создаю «query_otid_or» и 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);
Это не работает, новая запись вставлена … хотя это точно та же команда …
У кого-нибудь есть идеи?
Чтобы быть ясным, в вашем первом примере (через оболочку) результат запуска upsert заключается в том, что документ обновляется, поскольку запрос совпадает.
Кажется, это работает нормально для меня, я думаю, что вы преувеличиваете оба "\"packet.sccpCalling\""
а также "\"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' }")));
}