4

1 つのレコード (コミュニティ) の表現:

{
    "_id" : ObjectId("538a4734d6194c0e98000001"),
    "name" : "Darko",
    "description" : "Darko",
    "subdomain" : "darko",
    "domain" : "forum.dev",
    "created" : ISODate("2014-05-31T21:18:44.764Z"),
    "category" : "Art and Culture",
    "owner" : "53887456d6194c0f5b000001",
    "members" : [ 
        "53887456d6194c0f5b000001"
    ]
}

そして囲碁タイプ

Community struct {
    Id          bson.ObjectId `bson:"_id,omitempty" json:"id"`
    Name        string        `json:"name"`
    Description string        `bson:",omitempty" json:"description"`
    Subdomain   string        `bson:",omitempty" json:"subdomain"`
    Domain      string        `json:"domain"`
    Created     time.Time     `json:"created"`
    Category    string        `json:"category"`
    Owner       string        `json:"owner"`
    Banned      []string      `bson:",omitempty" json:"banned"`
    Members     []string      `json:"members"`
    Moderators  []string      `bson:",omitempty" json:"moderators"`
    Admins      []string      `bson:",omitempty" json:"admins"`
    Logo        string        `bson:",omitempty" json:"logo"`
    Stylesheets []string      `bson:",omitempty" json:"stylesheets"`
    Javascripts []string      `bson:",omitempty" json:"javascripts"`
}

では、すべてのコミュニティのリストを取得し、js またはGoCategory Art and Cultureのメンバー数で並べ替えたいと思います。members.lengthlen(Community.Members)

何かのようなものSELECT * FROM communities ORDER BY COUNT(members) WHERE category = 'Art and Culture'

入力または非整列化するカスタム型があります

CommunityDirectory struct {
    Id          bson.ObjectId `bson:"_id,omitempty" json:"id"`
    Name        string        `json:"name"`
    Description string        `bson:",omitempty" json:"description"`
    Subdomain   string        `bson:",omitempty" json:"subdomain"`
    Domain      string        `json:"domain"`
    Created     time.Time     `json:"created"`
    Category    string        `json:"category"`
    Logo        string        `bson:",omitempty" json:"logo"`
    Membercount int64         `bson:"membercount" json:"membercount"`
}

私がこれまでに持っているもの

func (ctx *CommunityContext) Directory() {
    pipe := ccommunity.Pipe([]bson.M{bson.M{"membercount": bson.M{"$size": "members"}}})
    iter := pipe.Iter()
    result := CommunityDirectory{}
    results := []CommunityDirectory{}
    for {
        if iter.Next(&result) {
            results = append(results, result)
            fmt.Println(result)
        } else {
            break
        }
    }
    ctx.JSON(results)
}

しかし、これは機能しません

db.communities.aggregate(
[
{"membercount": {$size:"members"}}
]
)

Error("Printing Stack Trace")@:0
()@src/mongo/shell/utils.js:37
([object Array])@src/mongo/shell/collection.js:866
@(shell):3

uncaught exception: aggregate failed: {
    "errmsg" : "exception: Unrecognized pipeline stage name: 'membercount'",
    "code" : 16436,
    "ok" : 0
}

したがって、membercount で並べ替えてすべてを検索し、新しい「仮想」フィールド membercount を割り当てる必要がありますが、カテゴリは「芸術と文化」のみです。

この点で、MongoDB はかなり複雑だと思います。

  1. mongodb クエリはどのようなものですか?

  2. Go/mgo ではどのように表示されますか?

4

1 に答える 1

9

集計フレームワークを初めて使用する場合に慣れる必要のある概念がいくつかあります。

シェルで動作するパイプラインの正しい形式は次のようになります。

db.communties.aggregate([

    // Match the documents first to filter and possibly make use of an index
    { "$match": {
        "category": "Art and Culture"
    }},

    // You include all fields when adding another and you want all
    { "$project": {
        "name": 1,
        "description": 1,
        "subdomain": 1,
        "domain": 1,
        "created": 1,
        "category": 1,
        "owner": 1,
        "members": 1,
        "memberCount": { "$size": "$members" }
    }},

    // $sort means "ORDER BY" in this case the ascending
    { "$sort": { "memberCount": 1 } },

    // Optionally project just the fields you need in the result
    { "$project": {
        "name": 1,
        "description": 1,
        "subdomain": 1,
        "domain": 1,
        "created": 1,
        "category": 1,
        "owner": 1,
        "members": 1
    }}
])

したがって、構造をまったく変更したくない場合を除き、「SELECT *」に直接相当するものは実際にはありません。ここでは、フィールド「memberCount」を追加する必要があるため、すべてのフィールドを指定する必要があります。ドキュメント内のすべてのフィールドをコピーする which を使用できる可能性があり$$ROOTますが、次のように、それを の別のフィールド/プロパティに割り当てる必要があります$project

{ "$project": {
    "_id": "$$ROOT",
    "memberCount": 1
 }}

しかし、もちろん、すべての「フィールド」は以前とまったく同じではなく、すべて接頭辞が付けられてい_id.ます。しかし、それは個人の好みの問題です。

次に慣れるには、常に$match最初に使用してみてください。これは、集計パイプラインの残りの部分で操作されるドキュメントを減らすのに役立つだけでなく、インデックスを使用してクエリを最適化する唯一の機会でもあります。他の段階でドキュメントを変更すると、インデックスが作成された元のソースではなくなるため、インデックスの使用はすべて終了します。実際にはSQLとそれほど違いはありませんが、セマンティクスは指定方法が多少異なります。「パイプライン」は Unix の「パイプ」|演算子と同じなので、最初に「マッチング」を行ってください。

並べ替えには、独自のパイプライン ステージがあります。したがって、$sortこれを行うには、パイプライン ステージの演算子を使用します。

ファイナル$projectはオプションです。ここでは、「並べ替え」に使用された「memberCount」フィールドを破棄しています。


mGo での使用法は次のようになります。

pipeline := [].bson.D{
    bson.M{"$match": bson.M{ "category": "Art and Culture" } },

    bson.M{"$project": bson.M{
        "name": 1,
        "description": 1,
        "subdomain": 1,
        "domain": 1,
        "created": 1,
        "category": 1,
        "owner": 1,
        "members": 1,
        "memberCount": bson.M{ "$size": "$members" }
    }},

    bson.M{ "$sort": bson.M{ "memberCount": 1 } },

    bson.M{ "$project": bson.M{
        "name": 1,
        "description": 1,
        "subdomain": 1,
        "domain": 1,
        "created": 1,
        "category": 1,
        "owner": 1,
        "members": 1
    }}
}

pipe := ccommunity.Pipe( pipeline )

したがって、実際には、そこにあるほとんどの例の形式とそれほど違いはありません。

集約パイプラインに適用される一般的な SQL クエリの他の例については、コア ドキュメントで提供されているSQL から集約へのマッピング チャートを参照してください。

于 2014-06-02T00:54:17.573 に答える