I have some categories which contain products, whereas you can add products to a category. This is a many to many relation, whereas products do not know of their relation to a category (as it is only saved inside a category). I will first post my setting and then the query which makes problems.
/** @ODM\Document */
class Category
{
/** @ODM\Id */
private $id;
/** @ODM\String */
private $name;
/** @ODM\ReferenceMany(targetDocument="Product", inversedBy="category") */
private $products;
public function setProducts($products)
{
$this->products = $products;
}
}
/** @ODM\Document */
class Product
{
/** @ODM\Id */
private $id;
/** @ODM\String */
private $name;
/** @ODM\Float */
private $price;
/** @ODM\ReferenceMany(targetDocument="Category", mappedBy="products") */
private $category;
}
In order to have some data, I create it like this:
$p1 = new Documents\Product();
$p1->setName('p1');
$p1->setPrice(1.99);
$p2 = new Documents\Product();
$p2->setName('p2');
$p2->setPrice(3.99);
$c1 = new Documents\Category();
$c1->setName('category1');
$c1->setProducts(array($p1, $p2));
$c2 = new Documents\Category();
$c2->setName('category2');
$c2->setProducts(array($p1, $p2));
$dm->persist($p1);
$dm->persist($p2);
$dm->persist($c1);
$dm->persist($c2);
$dm->flush();
Looking into MongoDB, I now have the following data:
db.Category.find()
{ "_id" : ObjectId("53e3d8d3e2afec2303d63afa"), "name" : "category1", "products" : [ DBRef("Product", ObjectId("53e3d8d3e2afec2303d63af8")), DBRef("Product", ObjectId("53e3d8d3e2afec2303d63af9")) ] }
{ "_id" : ObjectId("53e3d8d3e2afec2303d63afb"), "name" : "category2", "products" : [ DBRef("Product", ObjectId("53e3d8d3e2afec2303d63af8")), DBRef("Product", ObjectId("53e3d8d3e2afec2303d63af9")) ] }
db.Product.find()
{ "_id" : ObjectId("53e3d8d3e2afec2303d63af8"), "name" : "p1", "price" : 1.99 }
{ "_id" : ObjectId("53e3d8d3e2afec2303d63af9"), "name" : "p2", "price" : 3.99 }
I now want to query this data: Getting a product by id and getting all its categories, it belongs to:
$product = $dm->find('Documents\Product', '53e3d8d3e2afec2303d63af8');
var_export($product->getName());
$category = $product->getCategory();
var_export(sizeof($category));
foreach($category as $c){
var_export($c->getName());
}
// Outputs: 'p1' 2 'category1' 'category2'
But if I want to query the data the other way round: Getting a category and getting all its products, the category has:
$category = $dm->find('Documents\Category', '53e3d8d3e2afec2303d63afa');
var_export($category->getName());
$products = $category->getProducts();
var_export(sizeof($products));
foreach($products as $p){
var_export($p->getName());
}
// Outputs: 'category1' 2
No products are displayed and I get a fatal error:
Fatal error: Uncaught exception 'MongoCursorException' with message 'localhost:27017: Can't canonicalize query: BadValue $in needs an array' in /private/var/www/mongo/vendor/doctrine/mongodb/lib/Doctrine/MongoDB/Cursor.php on line 288
If I look into the MongoDB log, the query is as follows:
assertion 17287 Can't canonicalize query: BadValue $in needs an array ns:shop.Product query:{ $query: { _id: { $in: { 53e3d8d3e2afec2303d63af8: ObjectId('53e3d8d3e2afec2303d63af8'), 53e3d8d3e2afec2303d63af9: ObjectId('53e3d8d3e2afec2303d63af9') } } }, $orderby: [] }
I mean, the problem seems clear: $in
needs an array, but there is no JSON array given. But I don't know how to repair it. What am I doing wrong? If you can't answer this particular problem, can you provide me a working example for MongoDB with Doctrine, where you have a many to many relation like this and can query the data by both sides?
UPDATE: I maybe should have mentioned, which version of doctrine I use. I used this setting:
{
"require":{
"doctrine/common":"2.3.*",
"doctrine/dbal":"2.3.*",
"doctrine/orm":"*",
"doctrine/mongodb-odm": "1.0.0-BETA9"
}
}
Then I thought of updating to newest version available and used this setting:
{
"require":{
"doctrine/common":"2.4.*",
"doctrine/dbal":"2.3.*",
"doctrine/orm":"*",
"doctrine/mongodb-odm": "dev-master"
}
}
And voilà: Everything works fine.... OMG. But any explanations for this are still welcome, I want to know what happened here. Thanks a lot.