Provide my own value for mongodb $id index with PHP - php

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.

Related

MongoDB: Different return values on .find() at shell access, and at php

I started to use MongoDB 2.4.4, and I have a very iritating case for query-ing some post, by field in php.
In the mongoshell, the db.posts.find({page_id:345671} (for example) gives me a 293 count of document.
The php equivalent:
$connection = new Mongo('mongodb://localhost:27017');
$db = connection->selectDB('post_db');
$posts = $db->posts->find(array('page_id' => 345671));
Alway return a zero, but, when the a find array is empty, it gives back the entire collection.
Also, ->explain() and .explain() gaves me different params.
What am I do wrong? There's no sharding, no indexes, just some test data, i'm in the begining of the things.
SOLVED, many thanks to Vitaly Muminov!
"i'm not quite sure about that, but you can try setting ini_set('mongo.native_long', 1); or wrapping your numbers into MongoInt64 class"
The solution is wrap the number to MongoInt64!

PHP Arrays, ordered or not?

I have an Array of product types in PHP, it looks pretty much like this:
$types = [
0 => "cars",
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
So that when then user wants to get or save it, I can use the ID of the category to insert or get it from the database, like this:
select * from items where type = 0;
now, My doubt is the following: if I am using integer index keys, would it not be the same to use the following?
$types = ["cars", "motorbikes", "etc."];
Since PHP will give an integer auto-ordering.
Which one would you consider to be best practice in this case? The advantage of the first example seems to only be the fact that I can assign different keys, like for private categories or such, but I don't know really.
It is also important to consider that the values will need to be translated so, should I consider even just using IDs? like
$types = ["t1", "t2", "etc."];
and then insert the translation somewhere else?
There are 2 possible options.
Your current option 1 with manually set indexes.
A way better one - a table in the DB, holding these categories, which allow editing categories without losing the association between keys and names.
Your current option 2 is not an option at all - it will break the order the same moment you insert or delete a category
Here you set the index:
$types = [
3 => "airplanes"
index ^ ^ value
So, if you delete cars from the list, the index remain associated with it's value:
$types = [
1 => "motorbikes",
2 => "boats",
3 => "airplanes"
];
While if you don't set indexes manually
$types = ["motorbikes", "boats", "airplanes"];
airplanes will lose it's association, and become boats. It's not ht magic we expect from the web application
It all depends on the project. If I'm working with an array of items from the database I like the key to be the id from the database so it's available should I need it. If there's no need for the ids then there is no need to define a key. It will start at 0 anyways.
I think your first approach is a good one. You could even do it as default translation:
$types["en"] = []
Of course if you have a default language variable, you can use it from the start, and it will be much easier in the future to translate it further and expand
The arrays will be seen as the same so you can order it and take key as ID but it's not the best practice, all depends on how you design your relationship between arrays, php and database.
I might be missing your question but the array in PHP is ordered hash map basically. So ["cars", "motorcycles", "etc."] is guaranteed to preserver ordering (and have keys 0, 1, 2). But you might instead consider do the following
class AutoTypes {
const TYPE_CAR = 0;
const TYPE_MOTORCYCLE = 1;
const TYPE_BOAT = 2;
public static function getLabels() {
return array(self::TYPE_CAR => 'Car', self::TYPE_MOTORCYCLE => 'Motorcycle', self::TYPE_BOAT => 'Boat');
}
}
This way you can refer to the auto type by AutoTypes::CONSTANT. Because if you want to remove motorcycle at some point, not using clear indexes in the array, removing an item will brake your logic.
In my opinion, in this circumstance it's better to use
$types = ["cars", "motorbikes", "etc."];
As you say, PHP automatically assigns integer indexes starting from 0; so there's no need to specify the index that it would be assigned anyway.
It's up to you however, if you feel that it isn't clear enough just to declare an array without specifying the indexes manually then that's up to you. But personally I feel that it's obvious to any competent programmer and so therefore it's a waste of time and hard disk space to manually specify those indexes.

How to filter mongodb result for datatables?

I use this script to get the collection of my mongo database: http://datatables.net/development/server-side/php_mongodb
My question is: how to retrieve the rows where foo == 'mystring' only?
As you will notice (on line 29) from the source code in the file the mongo collection has been given the name: $m_collection as such:
$m_collection->find(array('foo' => 'mystring'))
Should work.
If this is not what you are looking for maybe you can be more specific and explain exactly what you are trying to do.
UPDATE
It has come to my attention you might want to instead edit the $searchTermsAll variable to search by this field in a doc. By the looks of it this PHP class links in the same as it would normally for SQL as such you should need to do anyhting special and can just enable filtering on datatables and add the value mystring to the foo field.
However to know if it is the right answer you will need to clarify.
UPDATE 2
A more destructive way of doing this that should keep filtering is to replace line 99 with:
$cursor = $m_collection->find(array_merge($searchTerms,
array('foo' => 'mystring')), $fields);
That will always make sure that your condition is added to the search terms but keeps the users own search terms.
Use as below
$cursor = $collection->find(array("foo" => "mystring"));
Here is more details: http://www.php.net/manual/en/mongo.queries.php

UpdateAttributes does not work

I have a problem with UpdateAttributes, it seem to not work for me.
When I issue:
$ret = $sphinx->UpdateAttributes ( "products", array ("status"), array(506607786 => array(10)) );
it returns 1, but search still returns status as old value for this.
When I try
$ret = $sphinx->UpdateAttributes ( "products", array ("status", "image_id"), array(506607786 => array(10, 6666)) );
it returns 0 (false)
Does this function even work ?
Ok I have found (sphinx docs are ugly) that when issuing updateAtrributes() from PHP app then I will not see the results in search command line. However one problem still
exist - I'm not able to update 2 attributes in one updateAtrributes() - seperatly they are fine - any clues why ?
When UpdateAttributes returns 0 (not false) it does not mean it didn't work, what it means is it didn't find anything to update, basically no updates commited. A return of -1 actually means this function did not work.
Make sure that 506607786 is actually an id in your Sphinx index and that products is the name of your index.
To make the question more helpful you can provide an example row from your table, preferrably the one used in this function defined as 506607786. You cna also provide a full set of your code to make it easier.
As a side note: UpdateAttributes does not act like a realtime index. You will need to filter on these attributes specifically in your query in order for sphinx to take their new values into consideration.

Using an Array as the Key for an Array in PHP

I need to create an association between an Array and a Number; as PHP lacks a Map type, I am trying using an array to achieve this:
$rowNumberbyRow = array();
$rowNumberByRow[$rowData] = $rowNumber;
However, when I evaluate the code, I get the following Error:
Warning: Illegal offset type
Just to note, the data stored in the array ($rowData) does not have any 'unique' values that I can use as a key for the $rowNumberByRow Array.
Thanks!
UPDATE:
To answer some of my commenters, I am trying to create a lookup table so that my application can find the row number for a given row in O(1) time.
PHP does have a map Class: It's called SplObjectStorage. It can be accessed with exactly the same syntax as a general array is (see Example #2 on the reference).
But to use the class you will have to use the ArrayObject class instead of arrays. It is handled exactly the same way arrays are and you can construct instances from arrays (e.g. $arrayObject = new ArrayObject($array)).
If you don't want to use those classes, you can also just create a function that creates unique hash-strings for your indexes. For example:
function myHash($array){
return implode('|',$array);
}
$rowNumberByRow[myHash($array)] = $rowNumber;
You will of course have to make sure that your hashes are indeed unique, and I would strongly suggest you use the SplObjectStorage and maybe read a little bit more about the SPL classes of php.
Why not just store the row number in the array? e.g:
$rowData['rowNumber'] = $rowNumber;
You could instead serialize the array, e.g:
$rowNumberByRow[serialize($rowData)] = $rowNumber;
However that's pretty inefficient.
In php you can use only scalar values as an array keys.
If your $rowNumber is unique - then you'd try to use the opposite relation direction. If it is not unique - then you don't have any possible solution I know.
The answer has been alredy given and accepted, but while i was searching for a similar problem, i found this question, and i felt like i should drop a line: when someone wants to use an array with values as keys for another array, it would be useful to use the function array_combine.
If i got the arrays correctly, you could use:
$rowNumberByRow = array_combine($rowData, $rowNumber);
Please take a look at the PHP manual to see some info about permitted values for the keys :)

Categories