聊天室案例
OrientDB满足丰富和复杂领域的建模。如果想开发一个聊天室,你可以使用任何类型去创建User和Room的关系。
我们建议避免使用边或者边连接的顶点去存储消息。最好的方式是使用Document API来为每一个Chat Room创建一个类,没有索引,可以快速获取最近的X条消息。事实上,OrientDB存储记录采用追加(append)的方式,RID也是自动生成递增的。
聊天室中2中最常使用的场景:
- 在聊天室里写一条消息
- 加载聊天室最新一页的消息
创建最初的模式
为了使用聊天室,最首要的规则就是创建一个基础的抽象类("ChatRoom"),让具体的类去表示每个聊天室。
创建基础的ChatRoom类
create class ChatRoom
alter class ChatRoom abstract true
create property ChatRoom.date datetime
create property ChatRoom.text string
create property ChatRoom.user LINK OUser
创建一个新的聊天室
create class ItalianRestaurant extends ChatRoom
类"ItalianRestaurant"将继承ChatRoom的所有属性。
为什么要创建一个基类?因为你有时需要执行跨聊天室的多态查询,例如获取用户"Luca"的所有信息:
select from ChatRoom where user.name = 'Luca'
在聊天室创建一条消息
在聊天室创建一条消息你可以使用以下代码:
public ODocument addMessage(String chatRoom, String message, OUser user) {
ODocument msg = new ODocument(chatRoom);
msg.field( "date", new Date() );
msg.field( "text", message );
msg.field( "user", user );
msg.save();
return msg;
}
例如:
addMessage("ItalianRestaurant", "Have you ever been at Ponza island?", database.getUser());
获取最新的消息
你可以很容易按照日期降序查询整页的数据, 其中使用到OrientDB的@rid
。 例如:
select from ItalianRestaurant order by @rid desc skip 0 limit 50
你可以写一个通用的方法获取某一页的信息,例如:
public Iterable<ODocument> loadMessages(String chatRoom, fromLast, pageSize) {
return graph.getRawGraph().command("select from " + chatRoom + " order by @rid desc skip " + fromLast + " limit " + pageSize).execute();
}
加载聊天室"ItalianRestaurant"的第二页数据, 查询变成:
select from ItalianRestaurant order by @rid desc skip 50 limit 50
这个查询非常快即使数百万数据,也是O(1)的复杂度。
限制
由于OrientDB只能处理32k的簇,所以最多只能有32k种聊天室(每个类默认创建一个物理簇)。 你可以重写 FreeNode, 但是32k个chat room类满足大多数情况的需求。
然而,你真的需要超过32k的聊天室,建议使用多个数据库(可以在一个服务器上,因为OrientDB可以同时处理数千个数据库)。
这种情况,你需要使用一个数据库处理所有的元数据,例如下面的类:
- ChatRoom, 包含了所有的聊天室。例如:
{ "@class": "ChatRoom", "description": "OrientDB public channel", "databaseName", "db1", "clusterName": "orientdb" }
- User, 包含了每个账户关联的所有ChatRoom类。
OrientDB不能处理跨数据库的连接,所以如果你想知道某个作者的消息,你需要通过RID在Metadata数据库中找到对应的聊天室(O(1)的复杂度)。