2016-09-25 13 views
1

私はMongo(好みのSQLの男)に慣れていて、誰かが設定したアプリケーションで作業しています。私はこのようなレコードに加え、さらに詳しい情報を持っています:更新時のMongoのクエリ

City: 
    name: "name" 
    State: ObjectId({id here}) 
    slug: "slug" 
    images: [images] 
    ... 

また、状態にはスラッグが入ったテキストフィールドがあります。私は、関連する都市のための都市のための新しいエントリーを作りたいと思う。したがって、画像、スラッグ、状態スラッグ、および名前の配列になります。私は以下のことを試してみましたが、私はstateSlugのクエリ情報で終わる:

db.getCollection('city').find(
{ 
    $or: 
     [ 
      {"name": "Camden"}, 
      {"name": "Virginia Beach"}, 
      {"name": "Annapolis"} 
     ] 
},{images:1, slug:1, state:1, name:1} 
).forEach(function(city){ 
    db.city.update({"name" : "Lewes"}, {$push:{'relatedCities': 
     { "images":city.images, 
      "slug":city.slug, 
      "name":city.name, 
      "stateSlug":db.state.find(city.state,{slug:1,_id:0}) 
     } 
    }}) 
}) 

私はこのクエリの作品を作ることができる方法はありますか?私はそれを動作させる方法を見つけ出すことができる場合、実行するために、この形式の情報をjsファイルに出力することができるexcelファイルとpythonスクリプトでクエリに使用される名前を持っています。助けてくれてありがとう!

答えて

1

あなたが取る必要があるアプローチは、(与えられた順序で)以下のパイプラインの手順を使用して集約パイプラインを実行している関係:

1)$matchパイプラインに入るフィルタ文書へ。式にequality checks for the value of the same fieldが含まれている場合は、$in演算子を$orの代わりに使用することを検討してください。これは、SQLのWHERE節に似ています。代わり

SELECT name, images, state, slug 
WHERE 
    (name = 'Camden') OR 
    (name = 'Virginia Beach') OR 
    (name = 'Annapolis') 

2の

SELECT name, images, state, slug 
WHERE name in ('Camden', 'Virginia Beach', 'Annapolis') 

$lookup左外側がstateコレクションである「参加」コレクションからの文書にフィルタリングする同じデータベースにunshardedコレクションに参加行います処理のために。 $lookupステージは、入力ドキュメントのstateフィールドと "joined"コレクションステートのドキュメントの_idフィールドとの一致が一致します。

3)$unwind - あなたはそれとして、配列を平らにすることができるように、あなたのパイプラインに$unwind段階を追加する必要がありますので、前$lookupパイプラインの結果から、新しいフィールドが配列であります非正規化フィールドとしてさらに処理する必要があります。

4)$groupすべてのドキュメントをグループ化し、前のパイプラインのフィールドを持つ配列relatedCitiesを作成するパイプラインステップ。 $groupパイプライン演算子は、SQLのGROUP BY節に似ています。 SQLでは、集約関数を使用しない限り、GROUP BYは使用できません。同じように、MongoDBでも集約関数を使用する必要があります。集計関数hereの詳細を読むことができます。

配列を作成する必要があるaccumulator演算子は、$pushです。あなたはSQL SELECT句とどうなるのかに似て -

5)$project最終段階は、その後、先行するパイプラインの文書からプロパティを選択するか、名前を変更するために使用されます。文字列リテラルで新しいフィールドを作成するには、$literal演算子が必要です。これは、SQLのASまたはALIASキーワードに似ています。


ここで注目すべきことは、パイプラインを実行するときにMongoDBパイプ演算子が互いにパイプすることです。ここで "Pipe"はLinuxの意味をとります。演算子の出力は、次の演算子の入力になります。各演算子の結果は、新しい文書集合です。 Mongoのは、上記のパイプラインを実行して、次のように:

collection | $match | $lookup | $unwind | $group | $project => result 

を今、あなたはモンゴシェルでこの集約パイプラインを実行すると、結果はあなたがcursortoArray()メソッドを使用するときに取得配列になりますcityコレクションでaggregate()メソッドを呼び出すことから戻りました。

あなたは、最初の集計フィールドを持つ新しいcity文書であるゼロインデックスを通じて結果配列内の唯一の要素にアクセスすることにより、cityコレクション内の新しい都市のエントリを作成し、上のsave()メソッドを使用することができますドキュメントを永続させるための都市コレクション。

次の例では、上記の概念を示しています

var pipeline = [ 
     { 
      "$match": { 
       "name": { "$in": ["Camden", "Virginia Beach", "Annapolis"] } 
      } 
     }, 
     { 
      "$lookup": { 
       "from": "state", 
       "localField": "state", 
       "foreignField": "_id", 
       "as": "states" 
      } 
     }, 
     { "$unwind": "$states" }, 
     { 
      "$group": { 
       "_id": null, 
       "relatedCities": { 
        "$push": { 
         "images": "$images", 
         "slug": "$slug", 
         "name": "$name", 
         "stateSlug": "$states.slug" 
        } 
       } 
      } 
     }, 
     { 
      "$project": { 
       "_id": 0, 
       "name": { "$literal": "Lewes" }, 
       "relatedCities": 1 
      } 
     }  
    ], 
    newCity = db.city.aggregate(pipeline).toArray()[0]; 

db.city.save(newCity); 
関連する問題