I have a php backend using phpredis (a php client for the redis server) to store key value pairs to a Redis server. The data I need to store is of this form:
"key1" => "v1", "v2", "v3"
"key2" => "m1", "m2", "m3"
"key3" => "n1", "n2", "n3"
...
Based on my research, I can set multiple keys in a redis using the mset command like so:
$redis->mSet(array('key0' => 'value0', 'key1' => 'value1'));
But what I actually need is something like this:
$redis->mSet(array('key0' => array('v1','v2','v3') , 'key1' => array('m1', 'm2', 'm3')));
But this just stores the value for each key as "Array" instead of the actual array specified.
Is this possible to do with a single command like mset or do I need to iterate my data and set each key separately using something like lPush?
phpredis documentation: https://github.com/phpredis/phpredis
So rather than using mSet you can probably use sADD to get your desired functionality.
$redis->sAdd($key, ...$data);
Full documentation on it here.
This would mean iterating and doing it in multiple steps for which I'd reccomend reading into Redis Pipelines and the non-shameless plug link which contains more information.
Which would look something like;
$redis = new Redis();
$pipeline = $redis->multi(Redis::PIPELINE);
foreach ($dataset as $data) {
$pipeline->sAdd($data['key'], ...$data['values']);
}
$pipeline->exec();
I can't think off the top of my head a way to do this in a singular operation, someone else might come along though who knows more than me :)
Edit: Looks like I misunderstood your question a little as it was more focused on doing this in a single operation. Hopefully the above is still useful but to my knowledge you'll have to do this with multiple.
Related
I've been hitting my head on this problem for some time now. I am working on a piece of software that creates a tree from a MySQL result checking for changes between each row to decide where in the tree to put the new data.
I'm now at a dead end while trying to understand how I can dynamically tell PHP to address different parts of my array.
I though about using variable variables but it doesn't seem to be working. To make my life easier I tried to set up a test file in which to test this behavior and this is the result...
$array = [
0 => [
"name" => "test"
],
1 => [
"name" => "test",
"data" => [
"content" => 5
]
]
];
$ref = 'array["1"]["name"]';
echo $ref."\n";
echo $$ref;
Output
array["1"]["name"]
Notice: Undefined variable: array["1"]["name"] in P:\xampp\htdocs\assets\php\test.php on line 23
I was instead expecting something like test.
I would also like to mention that I've tried the ${} method but I doesn't affect the array, but instead adds the data to another variable those rare times it doesn't output an error.
Anyone can help? Thanks!
after thinking about the problem once again I came up with a work-around to achieve the intended result.
I decided to use references make with &$var.
I, so, decided to tweak the code to create an array of each step to do to arrive at the intended location, instead of a string. Example follows:
// Old method
$ref = 'array["1"]["name"];
// New method
$ref = ["1", "name"];
The code then follows by cycling through the array referencing the original array but slowly deeper...
// Referencing the original array
$referencedArray = &$array;
// Going one step at the time inside the nested array
foreach ($ref as $k => $v) {
$referencedArray = &$referencedArray[$rav];
}
I believe this solution could fit my case, but if you have any suggestions please let me know.
I am having trouble bulk inserting documents with the PHP SDK. I have to insert each one individually like
$temp = $db->upsert("key here", "value here");
I can achieve about 500 / second. I have attempted to use the cbcdocloader but I cant generate json faster than just using the SDK to insert them directly. I am trying to insert multiple documents with one insert so I dont have to generate all the traffic. Is there a way to do this with an array structure like below?
$data = array("key 1"=> "value 1", "key 2" => "value 2")
I just did not believe it as I stumbled upon it somewhere a time ago, when I was searching for something else... But now I tried it, and it seems to work and I got a great performance increase (when doing a lot of inserts). It seems, you have to do it that way (using SDK 2.0 and upsert()):
$bucket->upsert(array(
'key1' => array('value' => 'value1'),
'key2' => array('value' => array('jsonkey' => 'jsonvalue')));
You have to use 'value' literally in the second array.
It seems, you also can specify options using:
$bucket->upsert(array(...), null, array('expiry' => 3600));
Maybe someone can verify this...
There is no bulk upload api call as such.
There is a semo of inserting in bulk http://docs.couchbase.com/couchbase-devguide-2.1/#performing-a-bulk-set.
Even, this does what you are already doing, in loops.
Apache SOLR calls for a quirky JSON format when you want to add multiple entries at once. ( http://wiki.apache.org/solr/UpdateJSON#Update_Commands -- notice the 'add' nodes)
In a nutshell, I need to be able to create JSON that looks like this:
{
"key": "val 1",
"key": "val 2"
}
In PHP, you can easily create an array, but this JSON structure calls for an object with two keys of identical name that are explicitly not in an array.
While json_encode can't do that directly, you can work around it. Try this:
$php_friendly_json = json_encode([
"key1" => "val 1",
"key2" => "val 2"
]);
$apache_weird_json = str_replace(["key1", "key2"], "key", $php_friendly_json);
Of course, be sure to pick key1 and key2 such that they aren't going to be in the values of your JSON!
You aren't going to be able to do this using json_encode because it's not valid JSON. (Keyspace collision)
You are going to need to assemble the object manually.
You might consider creating the individual items, then using implode(). Then you can prepend and append { and }.
This would actually feel cleaner to me then hacking away at PHP to get json encoding to work.
Suggested Alternative
I'm a big fan of the Solarium Project for PHP and Solr.
Bulk Adds and pretty easy take a look here: http://wiki.solarium-project.org/index.php/V2:BufferedAdd_plugin
Background: Using CodeIgniter with this MongoDB library.
This is my first go-round with mongodb and I'm enjoying it thus far. It's taken a while for me to separate myself from the sql way of thinking, but it is a perfect fit for my current project.
I'm trying to push an array into a document using...
$this->mongo_db->where(array('_id'=>$estimate_id))->push("measurements", $newData)->update('estimates');
If I encode $newData using json_encode($newData) I get {"levels":[{"level_qty":12,"level_uom":"ft"}]}
The problem is, when my function creates the measurements line in the mongodb document, it automatically starts an array with my insertion at [0]. Like this...
"measurements" : [ { "levels" : [ { "level_qty" : 12, "level_uom" : "ft" } ] }]
...leaving me with...
-measurements
--0
----levels
-----0
------level_qty => 2,
------level_uom => ft
What I really want is...
-measurements
--levels
---0
----level_qty => 2,
----level_uom => ft
I'm certain I'm missing something fairly elementary (i.e. php related & not mongodb related), but I'm an admitted amateur who has waded too deep.
$push is used to append a value to an array. In your example, measurements is an array and Mongo is appending $newData as its first element. This explains the 0 index between measurements and levels. In your desired result, measurements is an object equivalent to $newData (i.e. it has a levels property, which in turn has an array of objects within).
Either of the following examples should accomplish what you want:
// if $newData is {"levels": [{"level_qty":12,"level_uom":"ft"}]}
->set("measurements", $newData)
// if $newData is [{"level_qty":12,"level_uom":"ft"}]
->set("measurements.levels", $newData)
// if $newData is {"level_qty":12,"level_uom":"ft"}
->push("measurements.levels", $newData)
Note: $push is going to be more flexible if you want to append data with future updates, whereas $set will naturally overwrite the given field.
I want to insert my own unique value into the mongodb $id field
I already have a unique key and I don't want to take up extra space with yet another index.
How can I do this with the PHP API?
$collection->save(array('_id' => new MongoId('my_mongo_id'), 'foo' => 'bar'));
The docs above explain this in a general way, but to give you a PHP-specific example you simply set the _id value to your generated id when you create the document:
<?php
$mongo = new Mongo();
$collection = $mongo->dbName->collectionName;
$id = your_id_generator(); // I assume you have one
$collection->save(array('_id' => $id, 'foo' => 'bar'));
print_r( $collection->findOne(array('_id' => $id)) );
check this link
http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes
As long as you can guarantee uniqueness, you're not constrained to using the default "_id" MongoDB supplies.
Therefore, it's down to you how you generate this number. If you'd like to store this number inside MongoDB, then you could store it in a separate collection and increment it for every new URL required.
Incrementing a field is achieved by using the $inc verb, or you may want to take a look at how MongoDB can atomically update or increment a value.
Unique IDs with mongodb
I wrote a class to generate auto-increment values for Mongo in php
You can check out my project on gitgub https://github.com/snytkine/LampCMS
and look for /lib/Lampcms/MongoIncrementor class.
It basically keeps track of per-collection "nextValue" value
Works great for me, maybe it will work for you too.
Also feel free to examine my classes, I use MongoDB and php heavily, maybe you can learn something from the code or maybe can show/teach me some cool mongo/php code.
Hope this helps.