0

私は Mongodb を使用していますが、mysql に移行できます。私の問題は、次のようなデータで構成されるコレクションがあることです。

array(
"L"=>"cars",
"M"=>"wolkswagen"
)
array(
"L"=>"cars",
"M"=>"bmw"
)
array(
"L"=>"cars",
"M"=>"mercedes"
)


array(
"L"=>"bike",
"M"=>"bianchi"
)
array(
"L"=>"bike",
"M"=>"trek"
)
array(
"L"=>"bike",
"M"=>"brook"
)

結果として得たいのは、バイクと車ですが、それぞれ2つの結果なので、結果は次のようになります。

array(
"L"=>"cars",
"M"=>"some car"
)
array(
"L"=>"cars",
"M"=>"some car"
)


array(
"L"=>"bike",
"M"=>"some bike"
)
array(
"L"=>"bike",
"M"=>"some bike"
)

私は $in でこれをやろうとしましたが、うまくいかないようです。何かアイデアはありますか?

4

1 に答える 1

1

MongoDB 2.2+のAggregation Frameworkを使用してこの問題を解決する方法はいくつかあります。

残念ながら、2.2.2 の集約フレームワークは$sliceまだ or 配列サブセット演算子をサポートしていないため、追加の操作が必要です。

注: 以下の例ではmongoシェルを使用していますが、PHP ドライバーに変換するのは簡単です。

例 #1: Aggregation Framework を使用して 2 つの一致 (最初と最後) を抽出する

$firstグループ化ごとにどの 2 つの要素を取得するかを気にしないと仮定すると、 andを選択できます$last

db.cars.aggregate(

    // Group by $L and find the first and last elements
    { $group: {
        _id: '$L',
        first: { $first: "$M" },
        last: { $last: "$M" },
    }},

    // Add an extra $index for # of array elements
    { $project: {
        first: 1,
        last: 1,
        index: { $const:[0,1] }     
    }},

    // Split into document stream based on $index
    { $unwind: '$index' },

    // Re-group data using conditional to create array 
    { $group: {
        _id: '$_id',
        M: {
            $push: { $cond:[ {$eq:['$index', 0]}, '$first', '$last'] }
        }
    }}
)

出力例:

{
    "result" : [
        {
            "_id" : "cars",
            "M" : [
                "wolkswagen",
                "mercedes"
            ]
        },
        {
            "_id" : "bike",
            "M" : [
                "bianchi",
                "brook"
            ]
        }
    ],
    "ok" : 1
}

例 #2: Aggregation Framework を使用してセットを作成し、次に削減します

上記の代替手段は$addToSet、配列要素をトリムするための後処理ステップを使用した単純なパイプラインです。

var agg = db.cars.aggregate(
    { $group: {
        _id: '$L',
        'M': { $addToSet: "$M" },
    }}
)

// Iterate to trim each result to the desired # of elements
agg.result.forEach(function(doc) {
    // Note: you could randomly select 2 (or n) elements here
    doc.M = doc.M.slice(0,2);
})

出力形式は例 1 と同じですが、最初と最後の要素を選択する代わりに、例 2 (書かれているとおり) は最初の 2 つの要素を選択します。

于 2013-01-04T13:29:37.133 に答える