0

AppFog(Nodesterなど)でブログスタイルのWebアプリケーションを実行しています。これはNodeJS+Expressで記述されており、Mongooseフレームワークを使用してMongoDBに永続化します。

MongoDBはバージョン1.8であり、AppFogが2.2にアップグレードするかどうかはわかりません。

なぜこのイントロ?さて、今私の「投稿」は基本的な「ページ付けされた」視覚化で表示されます。つまり、モンゴからピックアップされ、日付の降順で一度に1ページずつ並べ替えられます。スニペットは次のとおりです。

Post
                .find({pubblicato:true})
                .populate("commenti")
                .sort("-dataInserimento")
                .skip(offset)
                .limit(archivePageSize)
                .exec(function(err,docs) {
                    var result = {};
                    result.postsArray = (!err) ? docs : [];
                    result.currentPage = currentPage;
                    result.pages = howManyPages;
                    cb(null, result);
            });

さて、私の目標は、「dataInserimento」でGROUP BYし、「日記」のような投稿を表示することです。つまり、次のようになります。

1ページ目=>2012/10/08:3件の投稿を表示

2ページ目=>2012/10/10:2つの投稿を表示します(2012/10/09には投稿がないため、白いページは許可しません)

3ページ目=>2012/10/11:35件の投稿など...

私の考えは、最初にグループ化してすべての日付のリストを取得し(そして、おそらく毎日の投稿を数えます)、次にページリンクを作成し、ページ(日付)にアクセスしたら、上記のようにクエリを実行し、パラメーターとして日付を追加します。

ソリューション

  • 集約フレームワークはそのために最適ですが、今はそのバージョンのMongoを手に入れることができません

  • 何らかの方法で.group()を使用しますが、シャード環境では機能しないという考えは私を興奮させません!:-(

  • MAP-REDUCEを書く!これが正しい方法だと思いますが、map()とreduce()をどのように書くべきか想像できません。

ちょっとした例を教えていただけませんか。

ありがとう

編集

ペシュキラの答えは正しいですが、それが正確に必要かどうかはわかりません。

つまり、/ archive / 2012/10/01、/ archive/2012/09/20などのURLがあります。

各ページには、投稿をクエリする日付があれば十分です。ただし、「次へ」または「前へ」のリンクを表示する必要があるため、投稿が含まれている翌日または前日があれば、それを知る必要があります。たぶん、現在よりも大きいまたは小さい日付の投稿をクエリして、最初の日付を取得できますか?

4

1 に答える 1

1

次のようなものがあるとします。

{
"author" : "john doe",
"title" : "Post 1",
"article" : "test",
"created" : ISODate("2012-02-17T00:00:00Z")
}
{
"author" : "john doe",
"title" : "Post 2",
"article" : "foo",
"created" : ISODate("2012-02-17T00:00:00Z")
}
{
"author" : "john doe",
"title" : "Post 3",
"article" : "bar",
"created" : ISODate("2012-02-18T00:00:00Z")
}
{
"author" : "john doe",
"title" : "Post 4",
"article" : "foo bar",
"created" : ISODate("2012-02-20T00:00:00Z")
}
{
"author" : "john doe",
"title" : "Post 5",
"article" : "lol cat",
"created" : ISODate("2012-02-20T00:00:00Z")
}

次に、次のように map reduce を使用できます。

地図

日付をキーとして、投稿のタイトルを出力するだけです。タイトルを _id に変更することができます。これはおそらくより便利です。日付の時刻を保存する場合は、キーとして日付のみ (時刻なし) を使用する必要があります。それ以外の場合、mongo は日付だけでなく日付時刻によってグループ化します。私のテストケースでは、すべての投稿の時刻が同じ 00:00:00 であるため、問題ではありません。

function map() {
  emit(this.created, this.title);
}

減らす

それ以上のことは何もせず、キーのすべての値を配列にプッシュするだけで、配列は結果オブジェクトにラップされます。これは、mongo が配列を reduce 関数の結果にすることを許可していないためです。

function reduce(key, values) {
  var array = [];
  var res = {posts:array};
  values.forEach(function (v) {res.posts.push(v);});
  return res;
}

実行する

を使用db.runCommand({mapreduce: "posts", map: map, reduce: reduce, out: {inline: 1}})すると、次の結果が出力されます。

{
"results" : [
    {
        "_id" : ISODate("2012-02-17T00:00:00Z"),
        "value" : {
            "posts" : [
                "Post 2",
                "Post 1"
            ]
        }
    },
    {
        "_id" : ISODate("2012-02-18T00:00:00Z"),
        "value" : "Post 3"
    },
    {
        "_id" : ISODate("2012-02-20T00:00:00Z"),
        "value" : {
            "posts" : [
                "Post 5",
                "Post 4"
            ]
        }
    }
],
...
}

これが役立つことを願っています

于 2012-10-10T08:25:56.660 に答える