Doctrine ODM 和无模式设计

发布于 2024-10-22 02:56:01 字数 540 浏览 5 评论 0原文

继续我关于 EAV 的问题,我正在考虑使用 MongoDB 来存储产品属性。

我将使用 MongoDB(或其他文档数据库)存储此应用程序的目录部分 - 类别、产品及其所有相关信息。

我的问题是,当使用 ODM 时,每个实体都有一个架构,该架构本质上忽略了使用 NoSQL 数据库的无模式优势,不是吗?

如果这是正确的,为什么有人会使用 ODM?

编辑:我发现一个相关问题,我可以使用哈希来实现产品属性功能吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小…楫夜泊 2024-10-29 02:56:01

解决方案是使用 @Hash

这是我做的一个非常基本的示例:

<?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;
    }

}

添加一些数据:

<?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();

然后查询,找到颜色为“黑色”且屏幕尺寸大于 20 的产品:

<?php

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

我仍然不确定这是否是做到这一点的最佳方法,我的研究仍在进行中。

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.

一城柳絮吹成雪 2024-10-29 02:56:01

尽管没有任何强制措施,但为集合提供一个基本架构是一个很好的做法。几乎所有 ODM 都允许您添加类中未指定的字段。假设应用程序允许,您还可以省略字段值。

然而,无模式数据存储的真正优势并不在于您的顶级字段可能会因文档而异,而在于这些字段可以是复杂的数据结构。每个产品都可能有一个数组属性字段,但该数组的内容可以任意长或短,并且可以包含具有各种结构的哈希值。如果您要求,您的 ODM 应该在这些哈希之上添加一个对象层。

最后一个优点是升级架构。在 SQL 中,添加或删除字段是一项整体操作,而且非常耗时。只需稍加规划,您就可以在访问文档时添加或删除字段。您只需要代码来处理过时的模式。

Even though nothing enforces this, it is a good practice to have a basic schema for a collection. Almost all ODM's allow you to add fields not specified in the class. Assuming the application allows it, you can also leave out field values.

The real advantage of a schemaless datastore, however, is not so much that your top level fields might vary form document to document, but that those fields can be complex data structures. Every product may have and attributes field that is an array, but the content of that array can be arbitrarily long or short, and can contain hashes with various structures. Your ODM should add an Object layer on top of these hashes if you ask it to.

The last advantage is in upgrading the schema. In SQL adding or removing a field is a monolithic operation that is also time consuming. With a little planning, you can add or remove fields from documents as they are accessed. You simply need code to deal with the out of date schema.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文