在Mongodb中嵌入或引用

eng*_*ave 3 mongodb nosql

我正在开发一个小应用程序,它将存储有关用户,帐户和交易的信息.用户将拥有许多帐户(可能少于10个),并且帐户将有许多交易(可能是1000个).阅读文档似乎表明嵌入如下是要走的路......

{
"username": "joe",
"accounts": [
    {
        "name": "account1",
        "transactions": [
            {
                "date": "2013-08-06",
                "desc": "transaction1",
                "amount": "123.45"
            },
            {
                "date": "2013-08-07",
                "desc": "transaction2",
                "amount": "123.45"
            },
            {
                "date": "2013-08-08",
                "desc": "transaction3",
                "amount": "123.45"
            }
        ]
    },
    {
        "name": "account2",
        "transactions": [
            {
                "date": "2013-08-06",
                "desc": "transaction1",
                "amount": "123.45"
            },
            {
                "date": "2013-08-07",
                "desc": "transaction2",
                "amount": "123.45"
            },
            {
                "date": "2013-08-08",
                "desc": "transaction3",
                "amount": "123.45"
            }
        ]
    }
 ]
}
Run Code Online (Sandbox Code Playgroud)

我的问题是......由于事务列表将在文档中增长到大约1000个,因此数据将变得支离破碎并降低性能.我是否更好地拥有一个文档来存储用户和不会增长的帐户,然后是一个单独的集合来存储引用帐户的事务.或者,还有更好的方法?

Der*_*ick 6

这不是要走的路.你有很多交易,你不知道你会得到多少.而不是这个,你应该存储它们像:

{
    "username": "joe",
    "name": "account1",
    "date": "2013-08-06",
    "desc": "transaction1",
    "amount": "123.45"
},
{
    "username": "joe",
    "name": "account1",
    "date": "2013-08-07",
    "desc": "transaction2",
    "amount": "123.45"
},
{
    "username": "joe",
    "name": "account1",
    "date": "2013-08-08",
    "desc": "transaction3",
    "amount": "123.45"
},
{
    "username": "joe",
    "name": "account2",
    "date": "2013-08-06",
    "desc": "transaction1",
    "amount": "123.45"
},
{
    "username": "joe",
    "name": "account2",
    "date": "2013-08-07",
    "desc": "transaction2",
    "amount": "123.45"
},
{
    "username": "joe",
    "name": "account2",
    "date": "2013-08-08",
    "desc": "transaction3",
    "amount": "123.45"
}
Run Code Online (Sandbox Code Playgroud)

在像MongoDB这样的NoSQL数据库中,你不应该害怕反规范化.正如您所注意到的,我甚至没有为用户打扰过单独的收藏.如果您的用户拥有每次交易必须显示的更多信息,您可能还需要考虑包含该信息.

如果您需要搜索或选择任何这些字段,那么不要忘记创建索引,例如:

// look up all transactions for an account
db.transactions.ensureIndex( { username: 1, name: 1 } ); 
Run Code Online (Sandbox Code Playgroud)

和:

// look up all transactions for "2013-08-06"
db.transactions.ensureIndex( { date: 1 } ); 
Run Code Online (Sandbox Code Playgroud)

等等

复制数据有很多好处.使用上面的模式,您可以拥有尽可能多的事务,并且您永远不会得到任何碎片,因为文档永远不会更改 - 您只需添加它们.这也提高了写入性能,并使其他查询更容易.

替代

另一种方法是将用户名/名称存储在集合中,并仅将其ID与事务一起使用:

帐户:

{
    "username": "joe",
    "name": "account1",
    "account_id": 42,
}
Run Code Online (Sandbox Code Playgroud)

交易方式:

{
    "account_id": 42,
    "date": "2013-08-06",
    "desc": "transaction1",
    "amount": "123.45"
},
Run Code Online (Sandbox Code Playgroud)

这会创建较小的交易文档,但它确实意味着您必须执行两个查询以获取用户信息.