2017-06-19 86 views
0

是否可以使用mongo-scala-driver macros從mongo數據庫讀取文檔,其中包含case個類中指定字段的附加字段?使用Mongo Scala驅動程序宏來讀取帶有附加嵌套字段的文檔

我預計未在案例類中指定的字段,但在反彙編中忽略文檔。但拋出異常。由於mongo db的模式較少的方法,不可能在案例類中指定全部字段集合。

我想反序列化文檔看起來像這樣JSON:

{ 
    "_id": 6, 
    "nestedOne": { 
     "nestedOneOne": 123, 
     "nestedOneTwo": 456 
    }, 
    "nestedTwo": { 
     "nestedTwoOne": 789 
    } 
} 

我期待下面的小例子的工作:

import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries} 
import org.bson.codecs.configuration.CodecRegistry 
import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY 
import org.mongodb.scala.bson.codecs.Macros._ 
import org.mongodb.scala.model.Filters 
import org.mongodb.scala.MongoClient 
import org.mongodb.scala.bson.collection.immutable.Document 
import scala.concurrent.Await 

import scala.concurrent.duration._ 

// prepare the case classes and register them 
case class TestDocument(_id: Int, nestedOne: Option[NestedOne]) 
case class NestedOne(nestedOneOne: Int, nestedOneTwo: Int) 
val testCodecRegistry: CodecRegistry = fromRegistries(
    fromProviders(classOf[TestDocument], classOf[NestedOne]), 
    DEFAULT_CODEC_REGISTRY 
) 

// prepare the test data & insert them 
val testDocument = Document(
    "_id" -> 6, 
    "nestedOne" -> Document("nestedOneOne" -> 123, "nestedOneTwo" -> 456), 
    "nestedTwo" -> Document("nestedTwoOne" -> 789) 
) 

val mongoClient = MongoClient("mongodb://localhost:1234") 
val database = mongoClient.getDatabase("testdatabase") 
val testCollection = database.getCollection("test_collection").withCodecRegistry(testCodecRegistry) 
Await.result(testCollection.insertOne(testDocument).toFuture, 2.minutes) 

// try to read and deserialize the document again 
val _ = Await.result(testCollection.find[TestDocument](Filters.equal("_id", 6)).toFuture(), 2.minutes) 

但以下異常被拋出:

head of empty list 
java.util.NoSuchElementException: head of empty list 
    at scala.collection.immutable.Nil$.head(List.scala:428) 
    at scala.collection.immutable.Nil$.head(List.scala:425) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.readDocument(MacroCodec.scala:204) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.readDocument$(MacroCodec.scala:193) 
    at de.peterschrott.mongotest.MongoTest$$anon$1$TestDocumentMacroCodec$3.readDocument(MongoTest.scala:29) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.readValue(MacroCodec.scala:173) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.readValue$(MacroCodec.scala:169) 
    at de.peterschrott.mongotest.MongoTest$$anon$1$TestDocumentMacroCodec$3.readValue(MongoTest.scala:29) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.decode(MacroCodec.scala:104) 
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.decode$(MacroCodec.scala:96) 
    at de.peterschrott.mongotest.MongoTest$$anon$1$TestDocumentMacroCodec$3.decode(MongoTest.scala:29) 
    at com.mongodb.operation.CommandResultArrayCodec.decode(CommandResultArrayCodec.java:52) 
    at com.mongodb.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:53) 
    at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:84) 
    at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:41) 
    at org.bson.codecs.configuration.LazyCodec.decode(LazyCodec.java:47) 
    at org.bson.codecs.BsonDocumentCodec.readValue(BsonDocumentCodec.java:101) 
    at com.mongodb.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:56) 
    at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:84) 
    at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:41) 
    at com.mongodb.connection.ReplyMessage.<init>(ReplyMessage.java:57) 
    at com.mongodb.connection.CommandProtocol.getResponseDocument(CommandProtocol.java:139) 
    at com.mongodb.connection.CommandProtocol.access$000(CommandProtocol.java:51) 
    at com.mongodb.connection.CommandProtocol$CommandResultCallback.callCallback(CommandProtocol.java:271) 
    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.invokeDirect(Invoker.java:157) 
    at sun.nio.ch.UnixAsynchronousSocketChannelImpl.implRead(UnixAsynchronousSocketChannelImpl.java:553) 
    at sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:276) 
    at sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297) 
    at com.mongodb.connection.AsynchronousSocketChannelStream.readAsync(AsynchronousSocketChannelStream.java:125) 
    at com.mongodb.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:444) 
    at com.mongodb.connection.InternalStreamConnection.access$2000(InternalStreamConnection.java:66) 
    at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.onResult(InternalStreamConnection.java:541) 
    at com.mongodb.connection.InternalStreamConnection$ResponseHeaderCallback.onResult(InternalStreamConnection.java:517) 
    at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) 
    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.UnixAsynchronousSocketChannelImpl.finishRead(UnixAsynchronousSocketChannelImpl.java:430) 
    at sun.nio.ch.UnixAsynchronousSocketChannelImpl.finish(UnixAsynchronousSocketChannelImpl.java:191) 
    at sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:213) 
    at sun.nio.ch.KQueuePort$EventHandlerTask.run(KQueuePort.java:301) 
    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) 

有沒有解決問題的方法?

+0

函數fromRegistries,waitForResult和fromProviders缺失。此外,變量數據庫丟失。 –

+0

您的測試文檔與案例類中表示的預期數據結構不匹配。錯誤信息可能會得到改進,我將着眼於未來的補充。 – Ross

回答

1

的問題是由於不同的數據類型:

case class TestDocument(_id: Long, nestedOne: Option[NestedOne]) 
case class NestedOne(nestedOneOne: Int, nestedOneTwo: Int) 
val testCodecRegistry: CodecRegistry = fromRegistries(
    fromProviders(classOf[TestDocument], classOf[NestedOne]), 
    DEFAULT_CODEC_REGISTRY 
) 

具有以下數據形狀:

Document("_id" -> 6L, 
     "nestedOne" -> Document("nestedOneOne" -> 1, "nestedOneTwo" -> 2)) 

您插入此數據形狀:那麼結果是

Document(
    "_id" -> 6L, 
    "nestedOne" -> List(Document("nestedOneOne" -> 123)), 
    "nestedTwo" -> List(Document("nestedTwoOne" -> 789)) 
) 

一個錯誤,我添加了SCALA-319來改善在這種情況下引發的錯誤。

+0

我看到我的例子的問題。我其實犯了一個錯誤。對不起,那個。 我更新了我的問題,而不是代碼,以便與您的建議保持一致。但是,如果文檔具有案例類中未指定的字段,我仍然會收到異常。 – peedeeX21

+2

已經在[SCALA-307](https://jira.mongodb.org/browse/SCALA-307)中修復,它將作爲2.2.0的一部分發布 - 快照現在可用。 – Ross

+0

@Ross快照在maven上不可用。有關如何向此快照添加依賴關係的提示?我沒有在我的case類中包含ObjectId字段,並且編解碼器宏無法工作,出現「空頭列表」異常。 –

相關問題