Вопрос

Пример Проблемы:

Сущности:

  • Пользователь содержит имя и список друзей (ссылки на пользователя)
  • Запись в блоге содержит заголовок, содержание, дату и Автора (Пользователя)

Требование:

Мне нужна страница, на которой отображается заголовок и ссылка на блог с последними 10 публикациями друга пользователя.Мне также хотелось бы иметь возможность постоянно перелистывать старые записи.

SQL - решение:

Итак, в стране sql это было бы что-то вроде:

select * from blog_post where user_id in (select friend_id from user_friend where user_id = :userId) order by date

Решения GAE, о которых я могу думать, следующие:

  • Загрузите пользователя, просмотрите список друзей и загрузите их последние записи в блоге.Наконец, объедините все записи в блоге, чтобы найти последние 10 записей в блоге
  • В записи в блоге есть список всех пользователей, у которых автор числится в друзьях.Это означало бы простое чтение, но привело бы к перегрузке квоты при добавлении друга, у которого много записей в блоге.

Я не верю, что какое-либо из этих решений будет масштабируемым.

Я уверен, что другие сталкивались с этой проблемой, но я искал, смотрел видео Google io, читал чужой код...Что я упускаю из виду?

Это было полезно?

Решение 2

Эта тема рассматривается в докладе по Google io:http://code.google.com/events/io/sessions/BuildingScalableComplexApps.html

В основном команда Google предлагает использовать свойства списка и то, что они называют объектами реляционного индекса, пример приложения можно найти здесь: http://pubsub-test.appspot.com/

Другие советы

Если вы посмотрите на то, как будет выполняться предоставленное вами SQL-решение, оно будет выглядеть в основном следующим образом:

  1. Извлеките список друзей текущего пользователя
  2. Для каждого пользователя в списке запустите индексную проверку последних сообщений
  3. Объединить - объедините все проверки, начиная с шага 2, остановившись, когда вы извлекли достаточное количество записей.

Вы можете самостоятельно выполнить точно такую же процедуру в App Engine, используя экземпляры запроса в качестве итераторов и выполняя над ними объединение слиянием.

Вы правы, что это не будет хорошо масштабироваться для большого количества друзей, но оно страдает от точно таких же проблем, что и реализация SQL, просто оно также не маскирует их:Выборка последних 20 (например) записей стоит примерно O (n log n) работы, где n - количество друзей.

"Загрузите пользователя, просмотрите список друзей и загрузите их последние записи в блоге".

Это все, что представляет собой соединение - вложенные циклы.Некоторые виды соединений представляют собой циклы с поисковыми запросами.Большинство поисковых запросов - это просто циклы;некоторые из них являются хэшами.

"Наконец, объедините все записи в блоге, чтобы найти последние 10 записей в блоге"

Это ЗАКАЗ с ОГРАНИЧЕНИЕМ.Это то, что база данных делает для вас.

Я не уверен, что в этом не масштабируемого;в любом случае, это то, что делает база данных.

Вот пример на python, взятый из http://pubsub-test.appspot.com/:

У кого-нибудь есть один для java?Спасибо.

from google.appengine.ext import webapp

from google.appengine.ext import db

class Message(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)
 receiver_id = db.ListProperty(int)

class SlimMessage(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)

class MessageIndex(db.Model):  
 receiver_id = db.ListProperty(int)

class MainHandler(webapp.RequestHandler):

 def get(self):
  receiver_id = int(self.request.get('receiver_id', '1'))
  key_only = self.request.get('key_only').lower() == 'on'
  if receiver_id:
    if key_only:
      keys = db.GqlQuery(
          'SELECT __key__ FROM MessageIndex WHERE receiver_id = :1',
          receiver_id).fetch(10)
      messages.extend(db.get([k.parent() for k in keys]))
    else:
      messages.extend(Message.gql('WHERE receiver_id = :1',
                      receiver_id).fetch(10))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top