9

私はMongoDbとnodejs(mongooseを使用)から始めています。

私はストーリーのコレクションを持っています、それらのそれぞれは1つ以上のタグを持つことができます、それはそのようなものです:

{
    title: "The red fox",
    content: "The red fox jumps away...",
    tags: [
        {
            tagname: "fairytale",
            user: "pippo"
        },
        {
            tagname: "funny",
            user: "pluto"
        },
        {
            tagname: "fox",
            user: "paperino"
        }
    ]
},

... other stories

今度はタグクラウドを作りたいです。

これは、すべてのタグについてストーリーをクエリすることを意味します。

リレーショナルの世界(MySQLなど)では、Storiesテーブル、Tagsテーブル、およびStories_Tagsテーブル(多対多)があります。次に、タグテーブルなどでクエリを実行します。

そうする方法はありますか?(確かにそうです)

はいの場合、それは良い習慣ですか?それとも、nosqlパラダイムを破りますか?

私のスキーマ設計のより良い方法を想像できますか?

4

4 に答える 4

10

集計フレームワークを使用してこれを行う方法を次に示します (リリースされたばかりの 2.2 を使用する必要があります)。

db.stories.aggregate(
[
    {
        "$unwind" : "$tags"
    },
    {
        "$group" : {
            "_id" : "$tags.tagname",
            "total" : {
                "$sum" : 1
            }
        }
    },
    {
        "$sort" : {
            "total" : -1
        }
    }
])

結果は次のようになります。

{
    "result" : [
        {
            "_id" : "fairytale",
            "total" : 3
        },
        {
            "_id" : "funny",
            "total" : 2
        },
        {
            "_id" : "silly",
            "total" : 1
        },
        {
            "_id" : "fox",
            "total" : 1
        }
    ],
    "ok" : 1
}
于 2012-08-29T01:34:47.803 に答える
2

モンゴへようこそ

データに最適な「スキーマ」は次のようになります。

ストーリーと呼ばれるコレクションを作成すると、各ストーリーはこのコレクション内のドキュメントになります。その後、次のような方法で簡単にデータをクエリできます。

db.stories.find({ "tags.tagname": "fairytale"}); // will find all documents that have fairytale as a tagname.

アップデート

db.stories.find({ "tags.tagname": { $exists : true }}); // will find all documents that have a tagname.

検索クエリのドット表記に注意してください。これが、mongo で配列/オブジェクトに到達する方法です。

于 2012-08-27T10:32:51.337 に答える
1

MRを使用してこれを実現できます。MRでは、タグを選択して投影するだけです。

var map = function(){
     for(var i=0;i<this.tags.length;i++){
         emit(this.tags[i].tagname, {count: 1});
     }
}

そして、あなたのリデュースは、基本的にそのタグが見られた回数を合計して、発行されたドキュメントを実行します。

最新の不安定な2.2にアップグレードする場合は、集約フレームワークを使用することもできます。集計フレームワークの$projectおよび$sumパイプラインを使用して、各投稿からタグを投影し、それらを合計してスコアベースのタグクラウドを作成し、合計に基づいて各タグのテキストのサイズを設定できます。

はいの場合、それは良い習慣ですか?それとも、nosqlパラダイムを破りますか?

これはMongoDBのかなり標準的な問題であり、解決できない問題です。再利用可能な構造では、複雑なクエリを実行する必要があります。幸い、2.2には保存するaggregationmフレームワークがあります。

これが良いアプローチか悪いアプローチかについては、それ自体はかなり標準的なアプローチであり、良いアプローチでも悪いアプローチでもありません。

構造を改善するために、一意のタグとその数を別のコレクションに事前に集約することができます。これにより、タグクラウドをリアルタイムで構築しやすくなります。

事前集約は、MRまたは集約フレームワークを使用せずにMRから通常取得する他のコレクションを作成する形式です。これは通常、アプリに基づくイベントであるため、ユーザーが投稿を作成するか、投稿にタグを付け直すと、次のような「tag_count」のコレクションへの事前集計イベントがトリガーされます。

{
    _id: {},
    tagname: "",
    count: 1
}

イベントがトリガーされると、アプリは投稿のタグをループし、基本的に次のように$incアップサートを実行します。

db.tag_count.update({tagname: 'whoop'}, {$inc: {count: 1}}, true);

これで、ブログ全体でタグのコレクションとその数がわかります。そこから、MRが行ったのと同じルートに進み、このコレクションにクエリを実行してデータを取得します。もちろん、削除イベントと更新イベントを処理する必要がありますが、一般的な考え方は理解できます。

于 2012-08-27T11:45:13.693 に答える
0

さて、さまざまな方法があります。そして、あなたの解決策とこれに違いはないと思います。

また、map_reduce メソッドをコピーして貼り付けて、タグ カウント ハッシュを出力することもできます。

于 2012-08-27T10:24:41.913 に答える