如何对集合中的数组进行排序

时间:2013-09-06 10:28:41

标签: mongodb symfony doctrine-mongodb

我一直在寻找在集合中对特定内部数组进行排序,我在symfony2中使用了doctrine-mongodb-bundle。 我的收藏:

"page":
{
    "_id": "56rgt46rt54h68rt4h6"
    "categories":
    [{
        "_id": "2g56rt1h65rt165165erg4"
        "products":[
            {"name":"A", "pos": 2},
            {"name":"B", "pos": 7},
            {"name":"C", "pos": 1},
            {"name":"D", "pos": 5}
        ]
    }]
}

我希望我有:

"page":
{
    "_id": "56rgt46rt54h68rt4h6"
    "categories":
    [{
        "_id": "2g56rt1h65rt165165erg4"
        "products":[
            {"name":"C", "pos": 1},
            {"name":"A", "pos": 2},
            {"name":"D", "pos": 5},
            {"name":"B", "pos": 7}
        ]
    }]
}

我的实体:

/**
 * @MongoDB\EmbeddedDocument
 */
class Category
{
    /**
     * @MongoDB\Id(strategy="auto")
     */
    protected $id;

    /**
     * @MongoDB\String
     */
    protected $name;

    /** @MongoDB\EmbedMany(targetDocument="\Document\Product") */
    private $products = array();
}

/**
 * @MongoDB\EmbeddedDocument
 */
class Product
{
    /**
     * @MongoDB\Int
     */
    protected $pos;

    /**
     * @MongoDB\String
     */
    protected $name;
}

我是DoctrineMongoDBBundle的新手,也许累积内部数组(EmbedMany)不是一个好主意,最好有几个集合。所以保存参考。

1 个答案:

答案 0 :(得分:3)

假设products数组中的项是唯一的,那么没有任何简单的服务器端支持来按照排序顺序维护此数组,就像MongoDB 2.4一样。给定嵌套数组的最佳选择是根据需要对应用程序逻辑中的数组进行排序(即插入/更新或检索/显示)。

数据建模注意事项

如果您需要对嵌套数组条目进行大量操作,则应考虑展平数据模型以使其更易于使用。 MongoDB的设计目标应该是拥有一个适合您的应用程序用例的数据模型,在插入/更新/查询的易用性之间具有可接受的性能平衡。如果这样做没有意义,你绝对不必在单个集合/查询中建模,并且你应该准备对数据进行非规范化(复制)。对于多对多关系,例如产品< =>类别通常是嵌入和反规范化哪个实体不经常更新(例如,在产品中嵌入类别)。

持久排序,上限数组(非唯一项目)

如果你想按排序顺序保存数组,那么这些项不是唯一的,MongoDB 2.4确实可以选择$push来排序数组,但必须与它结合使用切片(数组限制)。如果您对排序数组$push条目相同,则最终会出现重复项(因此这可能不是您所追求的)。

示例更新,假设您的示例中的page是集合名称:

db.page.update(
    // Query
    { "_id": "56rgt46rt54h68rt4h6" },

    // Update sorted array
    // NB: referring by array index position 0, as there isn't a named reference
    { $push : {
        "categories.0.products" : { 

            // List of new elements to push
            $each : [
                { "name" : "E", "pos": 3 }
            ],

            // Sort by pos (ascending)
            $sort : { "pos" : 1 },

            // Maximum number of array elements (required for $sort)
            $slice : -100
        }
    }}
)