2016-12-21 10 views
0

内部のサブ・プロパティの更新:今すぐMongoDBは:私は以下のように見える構造を有するネストされた配列のドキュメント

course: { // course 
    id, 
    coursename, 
    sections: { // has an array of sections 
    section: { 
     id, 
     sectionname 
     cards: { // each section has an array of cards 
     card: { 
      id 
      cardname 
     } 
     } 
    } 
    } 
} 

を、私は、カードIDを与えられています。 cardIDが301であるとします。コースやカードが保存されているセクションについての詳細はありません。私はcardIDしか持っていない。カード名を「Test 1」から「Test 2」に更新したいと思います。

カードIDのみを指定してカードの名前を更新する方法についての情報を入力してください。また、cardIdのみを使用して1つのカードにアクセスする方法に関する情報を提供してください。

私は次のクエリを実行した場合:

db.course.find({"sections.cards.id" : ObjectId("5859517447c4286d0f0639ee")}, 
{"sections.cards.$":1,_id:0}) 

を全セクションオブジェクトは、単一のカードを返す代わりに返されます。 cardIdのみを使用して単一のカードにアクセスする方法に関する情報を提供してください。

私が持っている文書の例:

{ 
    "_id" : ObjectId("58595041cfdc46100f92a985"), 
    "modelType" : "Course", 
    "name" : "c1", 
    "sections" : [ 
     { 
      "id" : ObjectId("5859504dcfdc46100f92a986"), 
      "name" : "s1", 
      "cards" : [ 
       { 
        "id" : ObjectId("58595057cfdc46100f92a987"), 
        "name" : "card1", 
       }, 
       { 
        "id" : ObjectId("5859506ccfdc46100f92a988"), 
        "name" : "card2" 
       } 
     ] 
     } 
    ] 
} 

のみカードIDを使用してカードを更新する方法についての情報を提供してください。

カードの名前を変更したいとします。どのように達成するのですか?

+0

何をしますか?あなたは例として文書を投稿できますか?どのプロパティがあなたの配列であり、あなたのオブジェクトであるかははっきりしていません。 – DennyHiu

+0

@DennyHiu、私はサンプルドキュメントを追加しました。私はカードIDだけを使って特定のカードを手に入れたい。 –

+0

@MaulikSonejiあなたは '$ elemMatch'を試しましたか? – Yogesh

答えて

2

私はこの答えはあなたのニーズに十分にあると思います:

db.collection.aggregate([ 
    {$unwind: "$sections"}, // unwind the array 
    {$unwind: "$sections.cards"}, // unwind the array 
    {$match: {"sections.cards.id": ObjectId("5859506ccfdc46100f92a988")}}, // filter 
    {$project: {_id: 0, id: "$sections.cards.id", name: "$sections.cards.name"}} // cut and clear any property that you don't need 
]) 

になる(私はあなたのサンプルを使用してそれをテスト):

{ 
    "name" : "card2", 
    "id" : ObjectId("5859506ccfdc46100f92a988") 
} 

説明:オフ

  1. ファーストaggregatemongojsまたはmongooseのようなライブラリを見つけて、その中でこれを行う方法それぞれのマニュアル)、
  2. 次にunwindセクションとその中のカード。
  3. 両方の手順の後に、unwindの操作の結果としてfilter文書が必要です。この場合:

    それは不可能だ更新する:どのカードを使用すると、ドキュメント内のプロパティを更新する

  4. リターンに結果

を必要としない任意のプロパティあなたのID

  • Clearと一致しますインデックスを知らない配列の中の要素なので、まずインデックス/位置を内部で調べる必要があります。私は考えることができ、最も簡単な方法はforを使用することです(あなたは2列-EDの配列であるため、私はmapReduce方法ははるかに複雑になると思う):

    // first, find the document, where xxx is the target card ID 
    db.collection.find({'sections.cards.id': ObjectId("xxx")}, function(err, reply){ 
        // iterates through the documents 
        for(var z = 0; z < reply.length; z++){ 
         // iterates through the `sections` 
         for(var y = 0; y < reply[z].sections.length; y++){ 
          // iterates through the `cards` 
          for(var x = 0; x < reply[z].sections[y].cards.length; x++){ 
            if(reply[z].sections[y].cards[x].id.toString() === "xxx")     
            { 
             // do what you want to do the card here 
             reply[z].sections[y].cards[x].name = "updated name"; 
            } 
          } 
         } 
    
         // save the updated doc one-by-one, 
         db.collection.update({_id: reply._id}, reply); 
        } 
    
    
    }); 
    

    最善の解決策

    最高解決策は次のとおりです。最初にこの種の文書はありません。スキーマフリーのデータベース・アプローチは、ドキュメント内にすべてを入れることができるわけではありません。次にドキュメントスキーマを設計する際には、データの機能とアクセシビリティを考慮する必要がありました。

    必要に応じて文書を合理化することができます。この場合、cardプロパティがcourseの独立したコレクションであることが明らかになっているので、courseドキュメントを分割する必要があります。両方のコレクションに参加する必要があると心配するなら、心配しないでください。 3.2 mongodbはこの種のアプリケーションのために$lookupを導入しています。

    あなたの人生を楽にしてくれるだけでなく、モンゴーのクエリも高速に実行できます。

  • +0

    また、カードの更新方法に関する情報も提供してください。 –

    +0

    このドキュメントを更新するための別の機能が必要になることは恐れられています。これを行う最も簡単な方法は 'update'メソッドを使うことです。私はすぐに私の答えを更新します – DennyHiu

    関連する問題