Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine ODM and schema-less design

Continuing on from my question about EAV, I'm considering using MongoDB to store product attributes.

I will store the catalogue part of this app - Categories, Products and all their related information - with MongoDB (or another document database).

My question is, when using an ODM, each entity has a schema, which essentially disregards the schema-less advantage of using a NoSQL database, does it not?

If this is correct, why would anyone use an ODM?

EDIT: I found a related question, could I achieve the product attributes functionality using a Hash?

like image 897
Cobby Avatar asked Mar 15 '11 01:03

Cobby


People also ask

Why do we call MongoDB as schema less database?

Mongodb does have a schema but its very loosely structured in that its simply objects, arrays and JavaScript types along with some other types like ObjectId, Date etc. forcing you to manage things in code in terms of schema.

What is schema less database What are the pros and cons of it?

A schemaless database manages information without the need for a blueprint. The onset of building a schemaless database doesn't rely on conforming to certain fields, tables, or data model structures. There is no Relational Database Management System (RDBMS) to enforce any specific kind of structure.

What the most important consideration while designing the schema for MongoDB?

When doing schema design in MongoDB there is more to consider than a blanket model for a “One-to-N” relationship model. We need to consider the size of “N” for our modeling because in this instance, size matters. One-to-one relationships can easily be handled with embedding a document inside another document.

Which of the following things while designing the schema in MongoDB?

Considerations while designing Schema in MongoDBCombine objects into one document if you will use them together. Otherwise separate them (but make sure there should not be need of joins). Duplicate the data (but limited) because disk space is cheap as compare to compute time. Do joins while write, not on read.


1 Answers

The solution is to use a @Hash

Here is a VERY basic example I did up:

<?php

/**
 * @Document
 */
class Product
{

    /**
     * @Id
     */
    private $id;

    /**
     * @String
     */
    private $name;

    /**
     * @Hash
     */
    private $attributes = array();

    public function getId()
    {
        return $this->id;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function addAttribute($name, $value)
    {
        $key = preg_replace('/[^a-z0-9\ \_]/i', '', $name);
        $key = preg_replace('/\s+/i', '_', $key);
        $key = strtolower($key);
        $this->attributes[$key] = array('value' =>$value, 'label' => $name);
    }

    public function getAttribute($name)
    {
        return $this->attributes[$name];
    }

    public function getAttributes()
    {
        return $this->attributes;
    }

}

Add some data:

<?php

$pen = new Product();
$pen->setName('Cool Pen');
$pen->addAttribute('Weight', 12);
$pen->addAttribute('Ink Colour', 'Red');
$pen->addAttribute('Colour', 'Black');

$tv = new Product();
$tv->setName('LED LCD TV');
$tv->addAttribute('Weight', 12550);
$tv->addAttribute('Screen Size', 32);
$tv->addAttribute('Colour', 'Black');

$dm->persist($pen);
$dm->persist($tv);

$dm->flush();

Then query, find a product with the colour "Black" and a Screen Size greater than 20:

<?php

$query = $dm->createQueryBuilder('Catalogue\Product');
$products = $query->field('attributes.colour.value')->equals('Black')
                ->field('attributes.screen_size.value')->gte(20)
                ->getQuery()->execute();

I'm still not sure if this is a best way to do this and my research is still ongoing.

like image 155
Cobby Avatar answered Sep 24 '22 08:09

Cobby