Подтвердить что ты не робот

"схема" для социальной сети

Я работаю над доказательством концептуального приложения для социальной сети в стиле Twitter, где около 500 тыс. пользователей. Я не уверен, как лучше всего разработать "схему"

Должен ли я встраивать пользовательские подписки или иметь отдельную коллекцию подписок и использовать ссылки db? Если я внедряю, мне все равно придется выполнить запрос, чтобы получить всех пользователей-последователей. например.

С учетом следующего пользователя:

{
 "username" : "alan",
 "photo": "123.jpg",
 "subscriptions" : [
    {"username" : "john", "status" : "accepted"},
    {"username" : "paul", "status" : "pending"}
  ]
}

чтобы найти всех подписчиков alan, мне нужно было бы запустить что-то вроде этого:

db.users.find({'subscriptions.username' : 'alan'});

с точки зрения производительности, заключается в том, что любой хуже или лучше, чем отдельный сбор подписей?

также при отображении списка подписчиков/подписчиков у меня в настоящее время возникают проблемы с n + 1, потому что документ подписки указывает мне имя пользователя целевого пользователя, но не другие атрибуты, которые могут мне понадобиться, такие как фотография профиля. Есть ли рекомендуемая практика для таких ситуаций?

спасибо Алан

4b9b3361

Ответ 1

Прежде всего, вы должны знать компромиссы, которые вы собираетесь получить с MongoDB и любой другой базой данных NoSQL (но поймите, что я ее поклонник). Если вы пытаетесь нормализовать свои данные полностью, вы делаете большую ошибку. Даже в реляционных базах данных, чем больше ваше приложение получает, тем больше ваши данные становятся денормализованными (см. этот пост от Hot Potato). Я видел это снова и снова. Вы не должны сходить с ума и сделать огромный беспорядок, но не беспокойтесь о повторении информации в двух местах. Одним из основных моментов (по моему мнению) NoSQL является то, что ваша схема перемещается в ваш код, а не только в базу данных.

Теперь, чтобы ответить на ваш вопрос, я думаю, что ваша первоначальная стратегия - это то, что я буду делать. MongoDB может размещать индексы на элементах, которые являются массивами, поэтому это сделает вещи намного быстрее, если вы ищете, сколько у друзей друзей. Но на самом деле единственный способ убедиться в этом - запустить какую-то тестовую программу, которая генерирует базу данных, полную имен и отношений.

Вы можете script добавить некоторый ввод в Python или Perl или что угодно, и использовать файл имен для создания некоторых отношений. Просмотрите сайт переписи, в котором есть список фамилий. Загрузите файл 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" ]
}

Чтобы вы могли иметь индекс для каждого типа подписки, таким образом, создавая такие запросы, как "Хой много людей, что Павел находится в ожидании?" и "Сколько людей подписывается на Пола?" супер быстрый в любом случае. Монгольское индексирование по значениям массива действительно является эпической победой.

Ответ 2

@Alan B: Я думаю, что вы полностью получаете MongoDB. Я согласен с версией @daveslab, но вы, вероятно, захотите добавить "последователей" тоже.

{
 "username" : "alan",
 "photo": "123.jpg",
 "acc_subs" : [ "john" ],
 "pnd_subs" : [ "paul" ]
 "acc_fol" : [ "mike", "ray" ],
 "pnd_fol" : [ "judy" ]
}

Да, это дублирует информацию. Это до уровня "бизнес-уровня", чтобы обеспечить правильное обновление этих данных в обоих местах. К сожалению, в Mongo нет транзакций, к счастью, у вас есть операция $addToSet, поэтому вы довольно безопасны.