Acabei de me deparar com essa pergunta e, embora seja antiga, pensei que seria útil adicionar algumas possibilidades não mencionadas nas respostas dadas. Além disso, as coisas mudaram um pouco nos últimos anos, portanto, vale ressaltar que SQL e NoSQL estão se aproximando.
Um dos comentadores levantou a sábia atitude de advertência de que "se os dados são relacionais, use relacionais". No entanto, esse comentário só faz sentido no mundo relacional, onde os esquemas sempre vêm antes do aplicativo.
MUNDO RELACIONAL: estruturar dados> Gravar aplicativo para obtê-lo
NOSQL WORLD: projetar aplicativo> estruturar dados de acordo
Mesmo que os dados sejam relacionais, o NoSQL ainda é uma opção. Por exemplo, relacionamentos um-para-muitos não são problema algum e são amplamente abordados nos documentos do MongoDB
UMA SOLUÇÃO DE 2015 PARA UM PROBLEMA DE 2010
Desde que esta pergunta foi publicada, houve sérias tentativas de aproximar o noSQL do SQL. A equipe liderada por Yannis Papakonstantinou da Universidade da Califórnia (San Diego) está trabalhando no FORWARD , uma implementação do SQL ++ que em breve poderá ser a solução para problemas persistentes, como o postado aqui.
Em um nível mais prático, o lançamento do Couchbase 4.0 significou que, pela primeira vez, você pode criar JOINs nativos no NoSQL. Eles usam seu próprio N1QL. Este é um exemplo de um JOIN
de seus tutoriais :
SELECT usr.personal_details, orders
FROM users_with_orders usr
USE KEYS "Elinor_33313792"
JOIN orders_with_users orders
ON KEYS ARRAY s.order_id FOR s IN usr.shipped_order_history END
O N1QL permite a maioria, se não todas, as operações SQL, incluindo agregação, filtragem, etc.
A SOLUÇÃO HÍBRIDA NÃO TÃO NOVA
Se o MongoDB ainda for a única opção, gostaria de voltar ao meu argumento de que o aplicativo deve ter precedência sobre a estrutura dos dados. Nenhuma das respostas menciona a incorporação híbrida, na qual a maioria dos dados consultados é incorporada no documento / objeto e as referências são mantidas para uma minoria de casos.
Exemplo: as informações (exceto o nome da função) podem esperar? o bootstrapping do aplicativo poderia ser mais rápido se você não solicitasse nada que o usuário ainda não precisas?
Pode ser esse o caso se o usuário efetuar login e precisar ver todas as opções para todas as funções às quais ele pertence. No entanto, o usuário é um "engenheiro" e as opções para essa função raramente são usadas. Isso significa que o aplicativo precisa apenas mostrar as opções para um engenheiro, caso ele queira clicar nelas.
Isso pode ser alcançado com um documento que informa ao aplicativo no início (1) quais funções o usuário pertence e (2) onde obter informações sobre um evento vinculado a uma função específica.
{_id: ObjectID(),
roles: [[“Engineer”, “ObjectId()”],
[“Administrator”, “ObjectId()”]]
}
Ou, melhor ainda, indexe o campo role.name na coleção de funções e talvez você não precise incorporar ObjectID () também.
Outro exemplo: as informações sobre TODAS as funções solicitadas TODAS AS VEZES?
Também pode ser que o usuário efetue login no painel e 90% do tempo execute tarefas vinculadas à função "Engenheiro". A incorporação híbrida pode ser feita para esse papel específico na íntegra e manter referências apenas para o resto.
{_id: ObjectID(),
roles: [{name: “Engineer”,
property1: value1,
property2: value2
},
[“Administrator”, “ObjectId()”]
]
}
Ser sem esquema não é apenas uma característica do NoSQL; pode ser uma vantagem nesse caso. É perfeitamente válido aninhar diferentes tipos de objetos na propriedade "Funções" de um objeto de usuário.