2014년 12월 9일 화요일

The dollar ($) prefixed field '$or' ... is not valid for storage

I have been using Mongo 2.4 + PHP and moved to Mongo 2.6. This told me to change to using MongoClient:
"The Mongo class is deprecated, please use the MongoClient class"

So I changed (as can be seen in PHP code below), but suddenly I ran into:

Fatal error: Uncaught exception 'MongoWriteConcernException' with message 'localhost:27017: The dollar ($) prefixed field '$or' in 'lbn_CockpitQuery.$or' is not valid for storage.' in /var/www/admin_functions.php:15 Stack trace: #0 /var/www/admin_functions.php(15): MongoCollection->save(Array) #1 /var/www/search_list.php(398): StoreAdminData('lbn_DetectedRel...', '') #2 /var/www/search_list.php(73): BuildQueryToIncludeDetectedRelease(Array) #3 {main} thrown in /var/www/admin_functions.php on line 15 

When it tries to store the following collection (or part of):

[lbn_CockpitQuery] => Array ( [$or] => Array ( [0] => Array ( [Unit] => NAC ) [1] => Array ( [Unit] => NAP ) [2] => Array ( [Unit] => NDS ) [3] => Array ( [Unit] => NFD ) [4] => Array ( [Unit] => NIF ) [5] => Array ( [Unit] => NOCP ) [6] => Array ( [Unit] => OBI ) [7] => Array ( [Unit] => OCT ) [8] => Array ( [Unit] => OCTA ) [9] => Array ( [Unit] => OEA ) [10] => Array ( [Unit] => ORK ) [11] => Array ( [Unit] => OSI ) [12] => Array ( [Unit] => OSO ) [13] => Array ( [Unit] => OSR ) [14] => Array ( [Unit] => OSS ) [15] => Array ( [Unit] => OST-E ) ) ) 

Basically, I just store a query that I use into a variable/key in a collection.
Apparently, this is not possible in Mongo 2.6 using MongoClient:
function StoreAdminData($key,$val)
{
   $m = new MongoClient();
   $db = $m->admin;
   $collection = $db->variables;
   $cursor = $collection->findone(array('Section' => 'General'));
   $cursor['Section']='General';
   $cursor[$key]=$val;
   $collection->save($cursor);
}

Any suggestion how to tackle this ? - Can I no longer store a query directly ?
Thanks a lot your answer is very appreciated.



$ is not allowed at the beginning of a field name, since in this position it is reserved to indicate query operators like $or, $addToSet, $, etc, and allowing it as part of field names would make the query language ambiguous. You can still store a query as a string value in a field

{
    "query" : "{ 'a' : { '$lte' : 5 } }",
    "sort" : "{ 'a' : 1 }"
}

or you could alter the key names so they no longer begin with $ and are valid for insertion into MongoDB

    "query" : { "a" : { "_DS_lte" : 5 } },
    "sort" : { "a" : 1 }
}

then modify the query after you retrieve it so it can be used. Naturally, you wouldn't want to allow _DS_ in key names in your documents in this example.

I don't know much about PHP, so perhaps these aren't the best way to store a query when using PHP, but they'll work.



Thanks a lot. But it works with mongo 2.4. I am puzzeled why it does not work under 2.6. I am asking as I basically end up having to redo all my code and it will take months.



As part of work upgrading the query engine from MongoDB 2.4 to MongoDB 2.6, a lot of restrictions, like on $ in field names, became strictly enforced. There's a listing of such changes in the 2.6 compatibility changes and a function db.upgradeCheckAllDBs() that will check a 2.4 instance for preparedness for upgrade to MongoDB 2.6 (it warns about field names starting with $, for instance).



Sounds like i have to eat a bitter pill here. Thanks :-)


댓글 없음:

댓글 쓰기