Spring Boot使用Couchbase TestContainer时抛出“Scope not found in CB datastore”异常
Spring Boot使用Couchbase TestContainer时抛出“Scope not found in CB datastore”异常
我帮你分析一下这个问题,从错误信息和你提供的代码来看,核心问题是命名不匹配加上Couchbase查询的语法规范问题,咱们一步步来解决:
问题定位
先看你抛出的错误核心内容:
com.couchbase.client.core.error.IndexFailureException: The server reported an issue with the underlying index {"completed":true,"coreId":"0x42adbe3e00000002","errors":[{"code":12021,"message":"Scope not found in CB datastore default:todo_list.invalid_token","retry":false}],...
再看错误里附带的查询语句:
SELECT `_class`, META(`invalid_token`).`id` AS __id, `TOKEN_ID`, `createdAt`, `createdBy`, `updatedAt`, `updatedBy` FROM `invalid_token` WHERE `_class` = "com.example.todowithcouchbase.auth.model.entity.InvalidTokenEntity" AND `TOKEN_ID` = $1
这里能发现两个明显问题:
- 你在TestContainer代码里创建的scope是
invalid-token(连字符),但查询语句里用的是invalid_token(下划线),命名完全不匹配; - 正确的Couchbase N1QL查询中,引用非默认scope下的collection,必须用
bucket_name.scope_name.collection_name的完整路径,而不是直接写collection名称。
解决方案
1. 统一所有地方的命名
先把所有涉及invalid-token的命名统一,要么全用连字符,要么全用下划线,推荐保持一致:
- 如果你要保留连字符
invalid-token:- 确保实体类上的注解正确:
@Document @Scope("invalid-token") @Collection("invalid-token") public class InvalidTokenEntity { // 你的字段和方法 } - 查询时必须用反引号括起来(因为连字符在N1QL里是特殊字符),比如正确的查询语句应该是:
SELECT `_class`, META(`todo_list`.`invalid-token`.`invalid-token`).`id` AS __id FROM `todo_list`.`invalid-token`.`invalid-token` WHERE `_class` = "com.example.todowithcouchbase.auth.model.entity.InvalidTokenEntity" AND `TOKEN_ID` = $1
- 确保实体类上的注解正确:
- 如果你嫌麻烦,直接改成下划线
invalid_token:- 修改TestContainer中创建scope和collection的代码,把
"invalid-token"改成"invalid_token"; - 修改application.yml里的scopes和collections配置,对应改成下划线;
- 实体类注解也改成
@Scope("invalid_token")和@Collection("invalid_token")。
- 修改TestContainer中创建scope和collection的代码,把
2. 优化TestContainer的初始化逻辑
你当前的初始化代码里,bucket的等待时间可能不够,Couchbase 7.x创建bucket后需要一点时间才能完全就绪,建议延长等待时间,同时确保scope和collection创建完成:
@BeforeAll public static void setup() { COUCHBASE_CONTAINER.start(); Cluster cluster = Cluster.connect( COUCHBASE_CONTAINER.getConnectionString(), COUCHBASE_CONTAINER.getUsername(), COUCHBASE_CONTAINER.getPassword() ); createBucketIfNotExists(cluster); Bucket bucket = cluster.bucket(BUCKET_NAME); // 延长等待时间到20秒,确保bucket完全就绪 bucket.waitUntilReady(Duration.ofSeconds(20)); CollectionManager collectionManager = bucket.collections(); // 创建scope和collection createScopeAndCollection(collectionManager, "invalid-token", "invalid-token"); createScopeAndCollection(collectionManager, "user", "user"); createScopeAndCollection(collectionManager, "task", "task"); createScopeAndCollection(collectionManager, "log", "log"); // 可选:打印所有scope和collection,确认创建成功 List<ScopeSpec> allScopes = collectionManager.getAllScopes(); log.info("已创建的Scope列表: {}", allScopes.stream().map(ScopeSpec::name).toList()); allScopes.forEach(scope -> { List<CollectionSpec> collections = collectionManager.getAllCollections(scope.name()); log.info("Scope {}下的Collection列表: {}", scope.name(), collections.stream().map(CollectionSpec::name).toList()); }); cluster.disconnect(); }
3. 检查Spring Boot配置的绑定
确保你的application.yml配置正确绑定到Spring Data Couchbase,如果是Spring Boot 3.x/Spring Data Couchbase 4.x,配置应该是在spring.data.couchbase下,而不是spring.couchbase:
spring: couchbase: connection-string: couchbase://${COUCHBASE_HOST:127.0.0.1} username: ${COUCHBASE_USERNAME:Administrator} password: ${COUCHBASE_PASSWORD:123456} bucket: ${COUCHBASE_BUCKET:todo_list} data: couchbase: scopes: user-scope: user task-scope: task invalid-token-scope : invalid-token log-scope: log collections: user-collection: user task-collection: task invalid-token-collection: invalid-token log-collection : log
验证
做完以上修改后,重新运行测试,应该就能解决Scope找不到的问题了。如果还有问题,看一下TestContainer打印的Scope和Collection日志,确认invalid-token确实被创建成功了。
备注:内容来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

