Open arj-mat opened 1 year ago
Thank you for getting in touch. The description outlines usage of an imperative repository but the stacktrace indicates a reactive flow via ReactiveMongoTemplate
which is puzzling. Also the use of @Aggregation
is not in line with the documentation.
// single stage
@Aggregation("{ '$project': { '_id' : '$lastname' } }")
// multiple stages
@Aggregation(pipeline = { "{ '$match' : { 'firstname' : '?0' } }", "{ '$project' : { '_id' : 0, 'lastname' : 1 } }" })
Maybe you can take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
Hi. I took some time to dig deeper into this issue and came to a couple findings:
Firstly, the way I "resumed" the code for posting here was not adequate and ended-up removing necessary parts to reproduce the problem.
Secondly, the way I was using @Aggregation
was indeed wrong and it induced me to believe the annotation was the root problem.
And finally, after some debugging, I realized that the failed command was an attempt to create indexes onto the nested document inside the view when having auto-index-creation
set to true
.
Here's the repository I made with reproducible code: https://github.com/arj-mat/spring-data-mongodb-issue-4465
// Document with an index
@Document("orders")
@Data
public class Order {
@Indexed
private Integer category;
private String description;
private Integer userId;
}
//View containing the Order document
@Document("users_orders_view")
@Data
public class UserOrderView {
private Integer userId;
private Set<Order> userOrders;
}
Raw "users_orders_view" aggregation pipeline:
[
{
$match: {
userId: 1,
},
},
{
$group: {
_id: "$userId",
descriptions: {
$first: {
$concatArrays:
"$userOrders.description",
},
},
},
},
]
Debugged command message:
{
"createIndexes": "users_orders_view",
"indexes": [
{
"key": {
"userOrders.category": 1
},
"name": "userOrders.category"
}
]
}
The invocation stack begins at MongoPersistentEntityIndexCreator#checkForAndCreateIndexes
, which is not able to distinct between documents and views, therefore attempting to create nested indexes in it.
Otherwise, using another class (not annotted with @Document
) to hold the contents of a document inside a view is a workaround in this scenario.
thanks @arj-mat for following on this topic. Let me take this to the team to discuss how we want to move forward.
Currently the components do not distinguish between a collection and a view. However, since MongoDB views are read only I can imagine extending the current @Document
annotation.
@interface Document {
boolean readOnly() default false;
// ...
}
@Document(readOnly = true)
@interface View {
@AliasFor(annotation = Document.class, attribute = "collection")
String collection() default "";
// ...
}
The above could serve multiple scenarios like
@View
CrudRepository
TLDR;
When annotating a query with
@Annotation
on a MongoRepository of a view, this UncategorizedMongoDbException is thrown:Command failed with error 166 (CommandNotSupportedOnView): 'Namespace my_database.my_view is a view, not a collection'
But reproducing the same query via the
aggregate
method of MongoTemplate causes no problems and returns the expected result.Detailed explanation
The project: JDK Corretto 17.0.2 Spring Boot 3.0.0
The view class:
The repository:
Full exception stacktrace:
org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 166 (CommandNotSupportedOnView): 'Namespace my_database.my_view is a view, not a collection' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "Namespace my_database.my_view is a view, not a collection", "code": 166, "codeName": "CommandNotSupportedOnView"} at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:136) ~[spring-data-mongodb-4.0.0.jar:4.0.0] at org.springframework.data.mongodb.core.ReactiveMongoTemplate.potentiallyConvertRuntimeException(ReactiveMongoTemplate.java:2574) ~[spring-data-mongodb-4.0.0.jar:4.0.0] at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$translateException$93(ReactiveMongoTemplate.java:2557) ~[spring-data-mongodb-4.0.0.jar:4.0.0] at reactor.core.publisher.Flux.lambda$onErrorMap$27(Flux.java:7088) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onError(MonoFlatMapMany.java:255) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onError(FluxConcatArray.java:207) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onError(MonoIgnoreElements.java:84) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:241) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:315) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) ~[reactor-core-3.5.0.jar:3.5.0] at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:201) ~[reactor-core-3.5.0.jar:3.5.0] at com.mongodb.reactivestreams.client.internal.MongoOperationPublisher.lambda$sinkToCallback$31(MongoOperationPublisher.java:573) ~[mongodb-driver-reactivestreams-4.8.0.jar:na] at com.mongodb.reactivestreams.client.internal.OperationExecutorImpl.lambda$execute$9(OperationExecutorImpl.java:126) ~[mongodb-driver-reactivestreams-4.8.0.jar:na] at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:46) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:312) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.operation.CreateIndexesOperation$2$1.onResult(CreateIndexesOperation.java:160) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.operation.CreateIndexesOperation$2$1.onResult(CreateIndexesOperation.java:157) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.operation.CommandOperationHelper.lambda$addingRetryableLabelCallback$22(CommandOperationHelper.java:493) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.operation.CommandOperationHelper.lambda$transformingWriteCallback$11(CommandOperationHelper.java:341) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:46) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor$1.onResult(DefaultServer.java:238) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:46) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.CommandProtocolImpl$1.onResult(CommandProtocolImpl.java:82) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:683) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.UsageTrackingInternalConnection$2.onResult(UsageTrackingInternalConnection.java:159) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:46) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:526) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:501) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:824) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:788) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:648) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:645) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:319) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:266) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:645) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection.access$600(InternalStreamConnection.java:89) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:778) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:763) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:648) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:645) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:319) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream.handleReadResponse(NettyStream.java:347) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream.access$1100(NettyStream.java:105) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:421) ~[mongodb-driver-core-4.8.0.jar:na] at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:418) ~[mongodb-driver-core-4.8.0.jar:na] at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.85.Final.jar:4.1.85.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.85.Final.jar:4.1.85.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.85.Final.jar:4.1.85.Final] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
The working code using MongoTemplate: