3

Raven をいじって、Twitter のようなシナリオでオブジェクトをモデル化する最善の方法を見つけようとしています。これまでにいくつかのオプションを考え出しましたが、どれが最適かはわかりません。

public class User{
    public string Id{get;set;}
    public List<string> Following{get;set;}
    public List<string> Followers{get;set;}
}

User オブジェクトは単純明快で、私がフォローしているユーザーと私をフォローしているユーザーの ID と ID のリストだけです。フォローしているユーザーからのすべての投稿を取得するために、フィードのセットアップに助けが必要です。

オプション 1 - 簡単な方法

これは、UserId だけに基づいて、私がフォローしている人々のすべての投稿を検索します。

public class Post{
    public string UserId{get;set;}
    public string Content{get;set;}
}

索引

public class Posts : AbstractIndexCreationTask<Post>{
    public Posts(){
        Map = results => from r in results
                         select new{
                             r.UserId
                         };
    }
}

クエリ

var posts = session.Query<Post,Posts>().Where(c=>c.UserId.In(peopleImFollowing));

これは当たり前のルートですが、悪臭がします。クエリの結果、一連の OR ステートメントが Lucene に送信されます。Raven が処理できる上限は約 1024 であるため、1 人のユーザーが 1000 人を超える人をフォローすることはできません。

オプション 2 - フォロワーごとに 1 つの投稿

public class Post{
    public string UserId{get;set;}
    public string RecipientId{get;set;}
    public string Content{get;set;}
}

新しい投稿の追加

foreach(string followerId in me.Followers){
   session.Store(new Post{
    UserId = me.UserId,
    RecipientId = followerId,
    Content = "foobar" });
}

これは従うのもクエリするのも簡単ですが、作成されるドキュメントが多すぎるように思えます...おそらくそれは問題ではありませんか?

オプション 3 - 受信者のリスト

これまでのところ、私はこれが一番好きです。

public class Post{
    public string UserId{get;set;}
    public List<string> Recipients{get;set;}
    public string Content{get;set;}
}

索引

public class Posts : AbstractIndexCreationTask<Post>{
    public Posts(){
        Map = results => from r in results
                         select new{
                             UserId = r.UserId,
                             Recipient = r.Recipients
                         }
    }
}

新しい投稿の追加

session.Store(new Post{
               UserId = me.Id,
               Recipients = me.Followers,
               Content = "foobar"
              });

クエリ

var posts = session.Query<Post,Posts>().Where(c=>c.Recipient == me.Id);

これが最善の方法のように思えますが、私は Lucene を使ったことがありません。誰かが 10,000 人のフォロワーを持っている場合、インデックスにとって問題になるでしょうか? すべてのユーザーにメッセージを投稿したい場合はどうすればよいでしょうか? おそらく別のアプローチがありますか?

4

1 に答える 1

1

私の見解では、オプション1のみが実際に機能し、1024を超えるユーザーをフォローするためのサポートが必要な場合は、RavenDBがluceneと通信する方法を調整することをお勧めします。

オプション2とオプション3は、新しいユーザーをフォローした後、それらの古いツイートをタイムラインに表示することを考慮していません。同様に、フォローを解除した後、これらのツイートをタイムラインから非表示にすることもできます。これらの2つのアプローチのいずれかでこれを実装する場合は、「フォロー」操作ですべてのツイートを複製し、「フォロー解除」でそれらを削除する必要があります。これにより、フォロー/フォロー解除は非常にコストのかかる操作になり、失敗する可能性もあります(ツイートの一部を含むサーバーが、これを実行しているときに利用できない場合はどうなりますか?)。

オプション2には、文字通り大量の重複データが生成されるという大きな欠点もあります。数百万のフォロワーと数千の投稿を持つ有名なユーザーについて考えてみてください。次に、これに何千もの有名なユーザーを掛けます...Twitterでさえそのような量のデータを処理することはできません。

オプション3には、すべてのluceneドキュメントにおそらく数百万の値を持つこの「受信者」フィールドがあるため、インデックスへのクエリが遅くなるという問題もあります。そして、あなたは何兆ものドキュメントを持っています...いいえ、私はルーセンの専門家ではありませんが、タイムラインを表示するのに十分な速さではないと思います(タイムラインを表示したいのはあなただけではないことを無視しても) )。

上で述べたように、オプション1のみが機能すると思います。多分他の誰かがより良いアプローチを持っています。ところで良い質問です。

于 2012-05-13T23:32:05.420 に答える