Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb ';模式';社交网络的设计_Mongodb_Nosql - Fatal编程技术网

Mongodb ';模式';社交网络的设计

Mongodb ';模式';社交网络的设计,mongodb,nosql,Mongodb,Nosql,我正在为一个拥有约50万用户的推特式社交网络开发一个概念验证应用程序。我不确定如何最好地设计“模式” 我应该嵌入用户的订阅,还是有一个单独的“订阅”集合并使用db引用?如果我嵌入,我仍然需要执行一个查询来获取用户的所有追随者。e、 g 给定以下用户: { "username" : "alan", "photo": "123.jpg", "subscriptions" : [ {"username" : "john", "status" : "accepted"}, {"us

我正在为一个拥有约50万用户的推特式社交网络开发一个概念验证应用程序。我不确定如何最好地设计“模式”

我应该嵌入用户的订阅,还是有一个单独的“订阅”集合并使用db引用?如果我嵌入,我仍然需要执行一个查询来获取用户的所有追随者。e、 g

给定以下用户:

{
 "username" : "alan",
 "photo": "123.jpg",
 "subscriptions" : [
    {"username" : "john", "status" : "accepted"},
    {"username" : "paul", "status" : "pending"}
  ]
}
要找到alan的所有订户,我必须运行以下程序:

db.users.find({'subscriptions.username' : 'alan'});
从性能的角度来看,这比使用单独的订阅集合更糟糕还是更好

此外,当显示订阅/订阅者列表时,我当前在n+1上遇到问题,因为订阅文档告诉我目标用户的用户名,但不告诉我可能需要的其他属性,例如配置文件照片。是否有针对此类情况的推荐做法

谢谢
Alan

首先,您应该知道使用MongoDB和任何其他NoSQL数据库将要实现的权衡(但要知道我是它的粉丝)。如果您试图完全规范化您的数据,那么您就犯了一个大错误。即使是在关系数据库中,应用程序越大,数据的非规范化程度就越高(见《烫手山芋》)。我已经看了很多遍了。你不应该发疯,把事情搞得一团糟,但不要担心在两个地方重复信息。NoSQL的一个要点(在我看来)是您的模式将移动到您的代码中,而不仅仅是移动到数据库中

现在,为了回答你的问题,我想你最初的策略就是我要做的。MongoDB可以将索引放在数组元素上,因此如果您想了解一个用户有多少友谊,那么这将使事情变得更快。但在现实中,唯一能真正确定的方法是运行某种测试程序,生成一个充满名称和关系的数据库

您可以用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
另外,一般来说,您的字段名似乎有点长。请记住,该集合中的每个文档都会重复字段名,因为您不能依赖任何其他文档中的一个字段。为了节省空间,一般的策略是使用较短的字段名,如“una”,而不是“username”,但这是一件小事。请参阅帖子中的建议

编辑:

实际上,在进一步思考您的问题时,我想再提出一个建议:将订阅类型划分为不同的字段,以提高索引的效率。例如,而不是:

{
 "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" ]
}

这样,您就可以为每种订阅类型创建一个索引,从而使查询“Hoy many people have Paul as pending?”和“有多少人订阅Paul?”以超快速的方式进行。Mongo对数组值的索引真的是一个史诗般的胜利。

@Alan B:我认为你完全得到了MongoDB。我同意@daveslab版本的数据,但您可能也想添加“追随者”


是的,这是重复的信息。由“业务层”来确保这两个站点中的数据都得到了正确更新。不幸的是,Mongo中没有事务,幸运的是,您有$addToSet操作,因此您非常安全。

不错的帖子,+1,但我不同意缩短名称。让他们尽可能长,不必向其他开发人员解释任何事情。然后根据需要进行配置/优化。如果名称在扩展时是一个重要的大小问题,那么重构。我真的很喜欢您的答案,即先通过查询进行搜索,然后存储以备以后查询
{
 "username" : "alan",
 "photo": "123.jpg",
 "acc_subs" : [ "john" ],
 "pnd_subs" : [ "paul" ]
 "acc_fol" : [ "mike", "ray" ],
 "pnd_fol" : [ "judy" ]
}