2016-07-10 8 views
0

私はmgoライブラリで一括アップサンプリングを実行しようとしています。私はdocumentationを一括アップセットに関して読んでいました。これはMongoDBを初めて使用したときです。更新するドキュメントのペアを用意しなければならないようです。Mgoフィールドの型が間違っています

私の機能では、すべての検索を実行してから、クエリの結果を使用してbulk.Upsert()操作のペアの既存の部分として使用しています。私はこれが正しい方法であるかどうかは分かりませんが、一度に〜65kのドキュメントをアップレイトする必要があります。

ここにstruct型と、前述のMongoDB操作を実行するためにチャネルから読み込むワーカー・プール関数があります。

// types from my project's `lib` package. 
type Auctions struct { 
    Auc   int `json:"auc" bson:"_id"` 
    Item   int `json:"item" bson:"item"` 
    Owner  string `json:"owner" bson:"owner"` 
    OwnerRealm string `json:"ownerRealm" bson:"ownerRealm"` 
    Bid   int `json:"bid" bson:"bid"` 
    Buyout  int `json:"buyout" bson:"buyout"` 
    Quantity  int `json:"quantity" bson:"quantity"` 
    TimeLeft  string `json:"timeLeft" bson:"timeLeft"` 
    Rand   int `json:"rand" bson:"rand"` 
    Seed   int `json:"seed" bson:"seed"` 
    Context  int `json:"context" bson:"context"` 
    BonusLists []struct { 
     BonusListID int `json:"bonusListId" bson:"bonusListId"` 
    } `json:"bonusLists,omitempty" bson:"bonusLists,omitempty"` 
    Modifiers []struct { 
     Type int `json:"type" bson:"type"` 
     Value int `json:"value" bson:"value"` 
    } `json:"modifiers,omitempty" bson:"modifiers,omitempty"` 
    PetSpeciesID int `json:"petSpeciesId,omitempty" bson:"petSpeciesId,omitempty"` 
    PetBreedID int `json:"petBreedId,omitempty" bson:"petBreedId,omitempty"` 
    PetLevel  int `json:"petLevel,omitempty" bson:"petLevel,omitempty"` 
    PetQualityID int `json:"petQualityId,omitempty" bson:"petQualityId,omitempty"` 
} 

type AuctionResponse struct { 
    Realms []struct { 
     Name string `json:"name"` 
     Slug string `json:"slug"` 
    } `json:"realms"` 
    Auctions []Auctions `json:"auctions"` 
} 

func (b *Blizzard) RealmAuctionGrabber(realms chan string, db *mgo.Database, wg *sync.WaitGroup) { 
    defer wg.Done() 
    for i := range realms { 
     NewReq, err := http.NewRequest("GET", fmt.Sprintf("%s/auction/data/%s", b.Url, i), nil) 
     if err != nil { 
      fmt.Printf("Cannot create new request for realm %s: %s", i, err) 
     } 

     // Update the request with the default parameters and grab the files links. 
     Request := PopulateDefaultParams(NewReq) 
     log.Debugf("downloading %s auction locations.", i) 
     Response, err := b.Client.Do(Request) 
     if err != nil { 
      fmt.Printf("Error request realm auction data: %s\n", err) 
     } 
     defer Response.Body.Close() 

     Body, err := ioutil.ReadAll(Response.Body) 
     if err != nil { 
      fmt.Printf("Error parsing request body: %s\n", err) 
     } 

     var AuctionResp lib.AuctionAPI 
     err = json.Unmarshal(Body, &AuctionResp) 
     if err != nil { 
      fmt.Printf("Error marshalling auction repsonse body: %s\n", err) 
     } 

     for _, x := range AuctionResp.Files { 
      NewDataReq, err := http.NewRequest("GET", x.URL, nil) 
      if err != nil { 
       log.Error(err) 
      } 

      AuctionResponse, err := b.Client.Do(NewDataReq) 
      if err != nil { 
       fmt.Printf("Error request realm auction data: %s\n", err) 
      } 
      defer Response.Body.Close() 

      AuctionBody, err := ioutil.ReadAll(AuctionResponse.Body) 
      if err != nil { 
       fmt.Printf("Error parsing request body: %s\n", err) 
      } 

      var AuctionData lib.AuctionResponse 
      err = json.Unmarshal(AuctionBody, &AuctionData) 

      // grab all the current records, then perform an Upsert! 
      var existing []lib.Auctions 
      col := db.C(i) 
      err = col.Find(nil).All(&existing) 
      if err != nil { 
       log.Error(err) 
      } 

      log.Infof("performing bulk upsert for %s", i) 

      auctionData, err := bson.Marshal(AuctionData.Auctions) 
      if err != nil { 
       log.Error("error marshalling bson: %s", err) 
      } 

      existingData, _ := bson.Marshal(existing) 
      bulk := db.C(i).Bulk() 
      bulk.Upsert(existingData, auctionData) 
      _, err = bulk.Run() 
      if err != nil { 
       log.Error("error performing upsert! error: ", err) 
      } 
     } 
    } 
} 

私がbulk.Upsert(existingData,auctionData)と呼んだ場合、問題はありません。私はbulk.Run()を呼び出すときにしかし、私はこのエラーメッセージをログに記録取得しています:

{"level":"error","msg":"error performing upsert! error: wrong type for 'q' field, expected object, found q: BinData(0, 0500000000)","time":"2016-07-09T16:53:45-07:00"} 

私はこれは私がAuction構造体にBSONタギングをやっているかに関係していると仮定していますが、私はよく分かりませんこれは私がMongoDBで働いたのは初めてです。今すぐデータベースにコレクションがありません

BSONタグ付けに関するエラーメッセージはありますか?どのように修正できますか?

答えて

1

これがまだ実際であるかどうかわかりません。ここでは、コードです:私は、実際のデータに正しかったかどうかを確認するために行われてきたいくつかの変更があります

package main 

import (
    "gopkg.in/mgo.v2" 
    "log" 
    "io/ioutil" 
    "encoding/json" 
    "gopkg.in/mgo.v2/bson" 
) 

type Auctions struct { 
    Auc int `json:"auc" bson:"_id"` 
    Owner string `json:"owner" bson:"owner"` 
} 

type AuctionResponse struct { 
    Auctions []Auctions `json:"auctions"` 
} 

func main() { 
    session, err := mgo.Dial("mongodb://127.0.0.1:27017/aucs") 

    if err != nil { 
     panic(err) 
    } 
    defer session.Close() 
    session.SetMode(mgo.Monotonic, true) 

    db := session.DB("aucs") 

    var AuctionData AuctionResponse 
    AuctionBody, _ := ioutil.ReadFile("auctions.json") 
    err = json.Unmarshal(AuctionBody, &AuctionData) 

    log.Println("performing bulk upsert for %s", "realm") 

    bulk := db.C("realm").Bulk() 
    for _, auc := range AuctionData.Auctions { 
     bulk.Upsert(bson.M{"_id": auc.Auc}, auc) 
    } 
    _, err = bulk.Run() 
    if err != nil { 
     log.Panic("error performing upsert! error: ", err) 
    } 
} 

は、私はそれが何が起こっているか理解することは難しいことではありません願っています。さて、少しモンゴーのことを説明しましょう。

  1. existingのドキュメントを取得する必要はありません。既存の文書を更新する前に、あるいは巨大なデータベースに挿入する前に、すべての文書を要求するのは奇妙なことです。あなたが実際に持っている、それはDBに挿入されます
    • selector文書(私はSQLので約WHERE条件としてそれについて考えることを好む)
    • document
    • mgoさんupsert機能は、2つのパラメータが必要ですセレクタクエリがバルクupsertの場合
  2. を失敗した場合bulk.Upsert(sel1, doc1, sel2, doc2, sel3, doc3)しかしのように一つのリクエストにプッシュするために利用可能なselector - document対の無制限の量がありますあなたの場合は、この機能を使用する必要はありません。
  3. upsertが1つの文書にのみ影響するため、selectorが最初に複数の文書に適合する場合でも、最初に更新されます。つまり、upsertUPDATE ... WHEREよりもMySQLのINSERT ... ON DUPLICATE KEY UPDATEに似ています。 (ユニークなオークションのIDを持つ)あなたの場合は、単一のupsert MySQLのクエリのようになります。私たちはループ内で複数のアップサートを行い、その後、一度に実行することができ

    INSERT INTO realm (auc, owner) VALUES ('1', 'Hogger') ON DUPLICATE KEY UPDATE owner = 'Hogger'; 
    
  4. bulkで。

+0

ああ、私はそれがよりうまくいく方法を見ます。ありがとう! – mxplusb

+0

@mynameismevinあなたを歓迎します:-) –

+0

私は最大バッチサイズのエラーを得ています。私は 'bulk.Upsert()'をバッチ100で実行し、次に 'bulk.Run()'を呼び出してそれらのアップをプッシュします。それを回避する適切な方法でなければなりません、正しい? – mxplusb

関連する問題