Прежде всего, вы должны знать, какие компромиссы вы получите с MongoDB и любой другой базой данных NoSQL (но поймите, что я фанат этого). Если вы пытаетесь полностью нормализовать ваши данные, вы делаете большую ошибку. Даже в реляционных базах данных чем больше становится ваше приложение, тем больше денормализуются ваши данные (см. этот пост * Hot2 Potato). Я видел это снова и снова. Вы не должны сходить с ума и делать огромный беспорядок, но не беспокойтесь о повторении информации в двух местах. Одним из основных моментов (на мой взгляд) NoSQL является то, что ваша схема перемещается в ваш код, а не только в базу данных.
Теперь, чтобы ответить на ваш вопрос, я думаю, что ваша первоначальная стратегия - это то, что я бы сделал. MongoDB может размещать индексы на элементах, которые являются массивами, так что это значительно ускорит процесс, если вы ищете, сколько дружеских отношений имеет пользователь. Но на самом деле единственный способ убедиться в этом - запустить какую-то тестовую программу, которая генерирует базу данных, полную имен и связей.
Вы можете записать некоторые входные данные в Python или Perl или что угодно, и использовать файл имен для генерации некоторых отношений. Посетите веб-сайт Census , на котором есть список фамилий. Скачайте файл dist.all.last
и напишите какую-нибудь программу вроде:
#! /usr/bin/env python
import random as rand
f = open('dist.all.last')
names = []
for line in f:
names.append(line.split()[0])
rels = {}
for name in names:
numOfFriends = rand.randint(0, 1000)
rels[name] = []
for i in range(numOfFriends):
newFriend = rand.choice(names)
if newFriend != name: #cannot be friends with yourself
rels[name].append(newFriend)
# take relationships (i.e. rels) and write them to MongoDB
Кроме того, как общее примечание, ваши имена полей кажутся довольно длинными. Помните, что имена полей повторяются с каждым документом в этой коллекции, потому что вы не можете полагаться на одно поле, находящееся в любом другом документе. Для экономии места общей стратегией является использование более коротких имен полей, таких как «unam» вместо «username», но это мелочь. Смотрите великий совет в этих двух сообщениях.
EDIT:
На самом деле, немного подумав о вашей проблеме, я хотел бы сделать еще одно предложение: разбить типы подписки на разные поля, чтобы сделать индексы более эффективными. Например, вместо:
{
"username" : "alan",
"photo": "123.jpg",
"subscriptions" : [
{"username" : "john", "status" : "accepted"},
{"username" : "paul", "status" : "pending"}
]
}
Как вы сказали выше, я бы сделал это:
{
"username" : "alan",
"photo": "123.jpg",
"acc_subs" : [ "john" ],
"pnd_subs" : [ "paul" ]
}
Чтобы у вас мог быть индекс для каждого типа подписки, таким образом, создавая запросы типа "Привет, у многих людей есть ожидающий Пол?" и "Сколько людей подписались на Павла?" супер быстрый в любом случае. Индексирование Mongo по значениям массива - это действительно грандиозная победа.