Pergunta

Eu estou querendo saber qual seria a melhor maneira de projetar uma aplicação social onde os membros fazem atividades e seguir outros membros de atividades usando o Google AppEngine.

Para ser mais específico, vamos assumir que temos essas entidades:

  • Usuários quem tem amigos
  • Actividades que representam ações realizadas pelos usuários (vamos dizer que cada um tem uma mensagem de seqüência de caracteres e um ReferenceProperty para o seu proprietário, usuário ou pode utilizar associação de pais através de appengine-chave)

A parte mais difícil é seguir o seu amigo atividades, o que significa agregar as atividades mais recentes de todos os seus amigos.Normalmente, o que seria uma associação entre as Atividades de tabela e sua lista de amigos, mas isso não é viável um projeto no appengine como não há junte-se a simular o que vai exigir de queima N consultas (onde N é o número de amigos) e, em seguida, mesclando na memória - muito caro e, provavelmente, irá exceder pedido de prazo...)

Atualmente estou pensando em implementar isso usando caixa de entrada filas em que a criação de uma nova Actividade que irá disparar um processo de plano de fundo que irá colocar a nova atividade-chave na "caixa de entrada" de cada usuário a seguir:

  • A obtenção de "Todos os usuários que seguem X" é um possível appengine consulta
  • Não muito caro lote de entrada para uma nova "caixa de Entrada" entidade que, basicamente, lojas de Usuário, Atividade-Chave) de tuplas.

Eu vou ser feliz para ouvi pensamento sobre este design ou sugestões alternativas, etc.

Foi útil?

Solução

Dê uma olhada no Construção Escalável, Complexo de Apps na App Engine (pdf), uma fascinante discurso proferido na Google I/O por Brett Slatkin.Ele aborda o problema da construção de uma escalável serviço de mensagens como o Twitter.

Aqui está a sua solução usando uma propriedade de lista:

class Message(db.Model):
    sender = db.StringProperty()
    body = db.TextProperty()

class MessageIndex(db.Model):
    #parent = a message
    receivers = db.StringListProperty()

indexes = MessageIndex.all(keys_only = True).filter('receivers = ', user_id)
keys = [k.parent() for k in indexes)
messages = db.get(keys)

Esta chave só consulta encontra a mensagem de índices com mais de um receptor igual ao especificado, sem anular a serialização e a serializar a lista de receptores.Em seguida, você usar esses índices para capturar somente as mensagens que você deseja.

Aqui o caminho errado para fazer isso:

class Message(db.Model):
    sender = db.StringProperty()
    receivers = db.StringListProperty()
    body = db.TextProperty()

messages = Message.all().filter('receivers =', user_id)

Este é ineficiente, pois as consultas têm para descompactar todos os resultados retornados pela consulta.Então, se você devolvido 100 mensagens com 1.000 usuários em cada receptores lista que você teria para anular a serialização de 100.000 (100 x 1000) lista de valores de propriedade.Muito caro no armazenamento de dados de latência e cpu.

Eu estava muito confuso com tudo isso, em primeiro lugar, então eu escrevi uma pequeno tutorial sobre como utilizar a propriedade de lista.Divirta-se :)

Outras dicas

Eu não sei se é o melhor design para uma aplicação social, mas Jaiku foi Portado para o App Engine Por seu criador original quando a empresa foi adquirida pelo Google, por isso deve ser razoável.

Veja a seção Atores, tigres e ursos, oh meu! dentro Design_funument.txt. As entidades são definidas em Common/models.py E as consultas estão em Common/api.py.

Robert, sobre sua solução proposta:

messages = Message.query(Message.receivers == user_id).fetch(projection=[Message.body])

Eu acho que o ndb.textproperty "corpo" não pode ser usado com projeções porque não é indexado. As projeções suportam apenas propriedades indexadas. A solução válida seria manter as 2 tabelas: Message e MessageIndex.

Eu acho que isso agora pode ser resolvido com as novas consultas de projeção no NDB.

class Message(ndb.Model):
    sender = ndb.StringProperty()
    receivers = ndb.StringProperty(repeated=True)
    body = ndb.TextProperty()

messages = Message.query(Message.receivers == user_id).fetch(projection=[Message.body])

Agora você não precisa lidar com o custo caro de desaperiar a propriedade da lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top