2017-01-27 12 views
0

EDITEDより明確化:MongoDBクエリフィルタが更新として実行されています

私はJavaの非同期ドライバを介してのMongoDB 3.4を使用
これは私のコレクションの指標の一つである:日間

posts:{orders.postReqID:1, unique:1} 

私は異常な問題を抱えていたし、それは私がこのような記録に直面しました私のデータベース:

posts: 
{ 
    ..., 
    orders 
    [ 
     ..., 
     { 
      // Please notice there is an implicit postReqID:null 
      viewCount: -1, 
      amount: 1 
     } 
    ] 
}, ... 

私は原因を知らなかったので、このようなサブ文書を何度も削除しました。 は、それから私は(私はこの分野のためのより多くのNULL値を入れることはできないだろう、一意のインデックスを持っていたので)問題を診断するorders.postReqID:nullで文書を置く:

{ //This is the document I inserted inside my db 
    ... 
    orders: 
    [ 
     { 
     postReqID:Null 
     date:0 
     viewCount:0 
     remaining:0 
     } 
    ] 
} 

これは私が容疑者だったクエリです:

posts.findOneAndUpdate(
      and(new Document("visits.userID", userID), 
       new Document("orders.postReqID", postReqID) 
       ), 
      new Document("$inc", 
           new Document("orders.$.viewCount", 1) 
           .append("orders.$.remaining", -1) 
         ) 
         .append("$set", new Document("orders.$.endDate", currentTime) 
             .append("visits.$.date", currentTime)), 
          (r, t) -> 
          { 
           if (t != null) 
           { 
            t.fillInStackTrace(); 
            t.printStackTrace(); 
           } 
          } 
         ) 

そして、私は(私のデシベルの内側にその文書を入れて、もう一度、このクエリを実行した後に)このようなエラーが発生します。

com.mongodb.MongoCommandException: Command failed with error 11000: 'E11000 duplicate key error collection: ViewMember.posts index: orders.postReqID_1 dup key: { : null }' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "E11000 duplicate key error collection: ViewMember.posts index: orders.postReqID_1 dup key: { : null }", "code" : 11000, "codeName" : "DuplicateKey" } 
at com.sunova.bot.MongoDBDriver$14.lambda$requestAsync$1(MongoDBDriver.java:768) 
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
at com.mongodb.async.client.MongoClientImpl$2$2.onResult(MongoClientImpl.java:144) 
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
at com.mongodb.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:368) 
at com.mongodb.operation.CommandOperationHelper$1.onResult(CommandOperationHelper.java:381) 
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor$1.onResult(DefaultServer.java:185) 
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
at com.mongodb.connection.CommandProtocol$CommandResultCallback.callCallback(CommandProtocol.java:275) 
at com.mongodb.connection.ResponseCallback.onResult(ResponseCallback.java:48) 
at com.mongodb.connection.ResponseCallback.onResult(ResponseCallback.java:23) 
at com.mongodb.connection.DefaultConnectionPool$PooledConnection$2.onResult(DefaultConnectionPool.java:470) 
at com.mongodb.connection.DefaultConnectionPool$PooledConnection$2.onResult(DefaultConnectionPool.java:464) 
at com.mongodb.connection.UsageTrackingInternalConnection$3.onResult(UsageTrackingInternalConnection.java:119) 
at com.mongodb.connection.UsageTrackingInternalConnection$3.onResult(UsageTrackingInternalConnection.java:115) 
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
at com.mongodb.connection.InternalStreamConnection.executeCallbackAndReceiveResponse(InternalStreamConnection.java:378) 
at com.mongodb.connection.InternalStreamConnection.access$1700(InternalStreamConnection.java:66) 
at com.mongodb.connection.InternalStreamConnection$ResponseBuffersCallback.onResult(InternalStreamConnection.java:420) 
at com.mongodb.connection.InternalStreamConnection$ResponseBuffersCallback.onResult(InternalStreamConnection.java:389) 
at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.onSuccess(InternalStreamConnection.java:562) 
at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.access$2200(InternalStreamConnection.java:517) 
at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback$ResponseBodyCallback.onResult(InternalStreamConnection.java:584) 
at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback$ResponseBodyCallback.onResult(InternalStreamConnection.java:568) 
at com.mongodb.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:447) 
at com.mongodb.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:444) 
at com.mongodb.connection.AsynchronousSocketChannelStream$BasicCompletionHandler.completed(AsynchronousSocketChannelStream.java:218) 
at com.mongodb.connection.AsynchronousSocketChannelStream$BasicCompletionHandler.completed(AsynchronousSocketChannelStream.java:201) 
at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) 
at sun.nio.ch.Invoker$2.run(Invoker.java:218) 
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 

この例外は、このクエリによって実行されるべきではない、このクエリによって行われた異常な更新が存在することを意味します。このクエリは、新しいサブ配列要素をordersサブドキュメントに挿入しないでください。これは何の原因になりますか?最初の文書(この質問の冒頭にある)を見ると、viewCountamountに2つのインクリメントが発生していることがわかりますが、このクエリで挿入されるのはordersです。 MongoDBは私が意図したサブ配列要素を更新せず、新しい要素をそこに置きます。

答えて

2

$positionalオペレータの使用が競合しています。

プレイ中に2つの配列インデックスvisitsordersがあります。 $andの評価順序に基づいて、1つのインデックス値に解決されます。

あなたのケースでは、ポジション演算子が、指定した条件のインデックス値visits.userIDにインデックスを設定するように見えます。

更新では一致するインデックスがない可能性がありますordersと入力したクエリフィールドと更新フィールドを使用してorderの新しいエントリが作成されます。

+0

これは、私の文書の2つの配列フィールド内を1つのクエリで検索できないということですか?他に何ができるのか教えていただけますか?これを解決するためにクエリを変更するにはどうすればよいですか? –

+0

私はポジション演算子を使用しないことを意味します。一度に1つの配列をクエリ部分から見つかった適切なインデックスで更新するだけで済みます。 – Veeram

+0

と思われます。ご回答いただきありがとうございます:)私は私のコードを変更し、それを受け入れたとしてあなたの答えをマークします。 –

0

既にフィールド値がnullのユーザーがいるようです。 nullドキュメントを見つけて削除するだけで、うまくいきます。この問題は、一般に、文書に固有の索引の索引付きフィールドの値がない場合、索引にはこの文書のNULL値が格納されます。

エラーを修正し、null値を持つ複数のドキュメントを使用する場合は、スパースインデックスを使用できます。ここでは、スパースについての説明は次のとおりです。

https://docs.mongodb.com/manual/core/index-sparse/

+0

あなたの応答に感謝します。私が言ったように、私は自分自身がなぜこのようなことが起こるかを診断するためにヌルフィールド値を入れました。クエリを見てください。ドキュメントの挿入は一切行われません。つまり、挿入された注文は存在しないはずです。postReqID'の値は、なぜ私は重複キーエラーを取得する? –

+0

私はあなたのコレクションインデックスで一意ではなく疎インデックスを試しましたか?あなたの問題を理解すれば、それはインデックスに関連するはずです。 – umtc

+0

Dude私は私のインデックスフィールドにnull値を必要としません、私はこのクエリは 'postReqID'ヌルのいくつかのサブ文書を置くと言います。私は数日間私のDBを観察し、このクエリが原因であることを理解しました。これは、例えば次のクエリによる挿入の1つです: 'orders:[...、{postReqID:null、残り:-1、viewCount:1}]'。このクエリは、このような更新を行うことは想定されていないが、あなたは参照してください! –

関連する問題