diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/CommonQueryContext.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/CommonQueryContext.kt index 8b14171c1d..7f9f583f96 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/CommonQueryContext.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/CommonQueryContext.kt @@ -52,21 +52,22 @@ open class CommonQueryContext( var repoList: List? = null fun findProjectId(): String { - if (projectId != null) { - return projectId!! - } + return if (projectId != null) projectId!! else find(TNode::projectId.name).apply { projectId = this } + } + + protected fun find(field: String): String { val rule = queryModel.rule if (rule is Rule.NestedRule && rule.relation == Rule.NestedRule.RelationType.AND) { - findProjectIdRule(rule.rules)?.let { - return it.value.toString().apply { projectId = this } + findRule(rule.rules, field)?.let { + return it.value.toString() } } - throw ErrorCodeException(CommonMessageCode.PARAMETER_MISSING, "projectId") + throw ErrorCodeException(CommonMessageCode.PARAMETER_MISSING, field) } - private fun findProjectIdRule(rules: List): Rule.QueryRule? { + private fun findRule(rules: List, field: String): Rule.QueryRule? { for (rule in rules) { - if (rule is Rule.QueryRule && rule.field == TNode::projectId.name) { + if (rule is Rule.QueryRule && rule.field == field) { return rule } } diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/MetadataRuleInterceptor.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/MetadataRuleInterceptor.kt index a31d2928aa..767ba0e6bc 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/MetadataRuleInterceptor.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/common/MetadataRuleInterceptor.kt @@ -39,12 +39,14 @@ import com.tencent.bkrepo.repository.constant.METADATA_PREFIX import com.tencent.bkrepo.repository.model.TMetadata import com.tencent.bkrepo.repository.model.TNode import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.stereotype.Component /** * 元数据规则拦截器 * * 条件构造器中传入元数据的条件是`metadata.key=value`,需要适配成mongodb的查询条件 */ +@Component class MetadataRuleInterceptor : QueryRuleInterceptor { override fun match(rule: Rule): Boolean { diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/node/NodeQueryInterpreter.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/node/NodeQueryInterpreter.kt index 591e0124ef..561661d0c6 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/node/NodeQueryInterpreter.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/node/NodeQueryInterpreter.kt @@ -51,7 +51,8 @@ class NodeQueryInterpreter @Autowired @Lazy constructor( private val permissionManager: PermissionManager, private val repoNameRuleInterceptor: RepoNameRuleInterceptor, private val repoTypeRuleInterceptor: RepoTypeRuleInterceptor, - private val localDatetimeRuleInterceptor: LocalDatetimeRuleInterceptor + private val localDatetimeRuleInterceptor: LocalDatetimeRuleInterceptor, + private val metadataRuleInterceptor: MetadataRuleInterceptor ) : CommonQueryInterpreter(permissionManager) { @PostConstruct @@ -60,7 +61,7 @@ class NodeQueryInterpreter @Autowired @Lazy constructor( addModelInterceptor(SelectFieldInterceptor()) addRuleInterceptor(repoTypeRuleInterceptor) addRuleInterceptor(repoNameRuleInterceptor) - addRuleInterceptor(MetadataRuleInterceptor()) + addRuleInterceptor(metadataRuleInterceptor) addRuleInterceptor(localDatetimeRuleInterceptor) } diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageQueryContext.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageQueryContext.kt index fc9667209d..da011038f0 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageQueryContext.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageQueryContext.kt @@ -41,4 +41,13 @@ class PackageQueryContext( override var permissionChecked: Boolean = false, override val mongoQuery: Query, override val interpreter: MongoQueryInterpreter -) : CommonQueryContext(queryModel, permissionChecked, mongoQuery, interpreter) +) : CommonQueryContext(queryModel, permissionChecked, mongoQuery, interpreter) { + + private var repoType: String? = null + + val matchedVersions: MutableMap> = mutableMapOf() + + fun findRepoType(): String { + return if (repoType != null) repoType!! else find("repoType").apply { repoType = this } + } +} diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageSearchInterpreter.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageSearchInterpreter.kt index 0901f55380..7b52a3b9b9 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageSearchInterpreter.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/PackageSearchInterpreter.kt @@ -36,7 +36,6 @@ import com.tencent.bkrepo.common.query.model.QueryModel import com.tencent.bkrepo.common.security.manager.PermissionManager import com.tencent.bkrepo.repository.search.common.CommonQueryInterpreter import com.tencent.bkrepo.repository.search.common.LocalDatetimeRuleInterceptor -import com.tencent.bkrepo.repository.search.common.MetadataRuleInterceptor import com.tencent.bkrepo.repository.search.common.ModelValidateInterceptor import com.tencent.bkrepo.repository.search.common.RepoNameRuleInterceptor import com.tencent.bkrepo.repository.search.common.RepoTypeRuleInterceptor @@ -50,7 +49,10 @@ class PackageSearchInterpreter( private val permissionManager: PermissionManager, private val repoNameRuleInterceptor: RepoNameRuleInterceptor, private val repoTypeRuleInterceptor: RepoTypeRuleInterceptor, - private val localDatetimeRuleInterceptor: LocalDatetimeRuleInterceptor + private val localDatetimeRuleInterceptor: LocalDatetimeRuleInterceptor, + private val versionNameRuleInterceptor: VersionNameRuleInterceptor, + private val versionMetadataRuleInterceptor: VersionMetadataRuleInterceptor, + private val versionChecksumRuleInterceptor: VersionChecksumRuleInterceptor ) : CommonQueryInterpreter(permissionManager) { @PostConstruct @@ -59,8 +61,10 @@ class PackageSearchInterpreter( addModelInterceptor(SelectFieldInterceptor()) addRuleInterceptor(repoTypeRuleInterceptor) addRuleInterceptor(repoNameRuleInterceptor) - addRuleInterceptor(MetadataRuleInterceptor()) + addRuleInterceptor(versionMetadataRuleInterceptor) addRuleInterceptor(localDatetimeRuleInterceptor) + addRuleInterceptor(versionNameRuleInterceptor) + addRuleInterceptor(versionChecksumRuleInterceptor) } override fun initContext(queryModel: QueryModel, mongoQuery: Query): QueryContext { diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionChecksumRuleInterceptor.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionChecksumRuleInterceptor.kt new file mode 100644 index 0000000000..e4aa7b5cb8 --- /dev/null +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionChecksumRuleInterceptor.kt @@ -0,0 +1,107 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.tencent.bkrepo.repository.search.packages + +import com.tencent.bkrepo.common.api.exception.ErrorCodeException +import com.tencent.bkrepo.common.api.message.CommonMessageCode +import com.tencent.bkrepo.common.artifact.pojo.RepositoryType +import com.tencent.bkrepo.common.query.enums.OperationType +import com.tencent.bkrepo.common.query.model.Rule +import com.tencent.bkrepo.common.security.util.SecurityUtils +import com.tencent.bkrepo.repository.dao.NodeDao +import com.tencent.bkrepo.repository.dao.PackageVersionDao +import com.tencent.bkrepo.repository.model.TNode +import com.tencent.bkrepo.repository.model.TPackageVersion +import com.tencent.bkrepo.repository.pojo.repo.RepoListOption +import com.tencent.bkrepo.repository.service.repo.RepositoryService +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.data.mongodb.core.query.Query +import org.springframework.data.mongodb.core.query.inValues +import org.springframework.data.mongodb.core.query.isEqualTo +import org.springframework.stereotype.Component + +/** + * 版本Checksum规则拦截器, 查询包版本Checksum需要在嵌套查询规则列表中指定projectId和repoType条件,且均为EQ操作 + */ +@Component +class VersionChecksumRuleInterceptor( + override val packageVersionDao: PackageVersionDao, + private val nodeDao: NodeDao, + private val repositoryService: RepositoryService +) : VersionRuleInterceptor(packageVersionDao) { + + override fun match(rule: Rule): Boolean { + return rule is Rule.QueryRule && rule.field in CHECKSUM_FIELDS + } + + override fun getVersionCriteria(rule: Rule, context: PackageQueryContext): Criteria { + with(rule as Rule.QueryRule) { + if (operation != OperationType.EQ) { + throw ErrorCodeException(CommonMessageCode.METHOD_NOT_ALLOWED, "$field only support EQ operation type.") + } + val projectId = context.findProjectId() + val repoType = context.findRepoType().toUpperCase() + val userId = SecurityUtils.getUserId() + // 筛选有权限的仓库列表, docker和oci仓库互相兼容 + val repoList = if (repoType in listOf(RepositoryType.DOCKER.name, RepositoryType.OCI.name)) { + val dockerRepoList = repositoryService.listPermissionRepo( + userId, projectId, RepoListOption(type = RepositoryType.DOCKER.name) + ) + val ociRepoList = repositoryService.listPermissionRepo( + userId, projectId, RepoListOption(type = RepositoryType.OCI.name) + ) + dockerRepoList + ociRepoList + } else + repositoryService.listPermissionRepo(userId, projectId, RepoListOption(type = repoType)) + // 从有权限的仓库列表查询符合checksum规则的节点 + val nodeQuery = Query( + Criteria.where(TNode::projectId.name).isEqualTo(projectId) + .and(TNode::repoName.name).inValues(repoList.map { it.name }) + .and(field).isEqualTo(value.toString()) + ) + val fullPaths = queryRecords(nodeQuery) { q -> nodeDao.find(q) }.map { it.fullPath } + // 转换为package_version查询条件 + return if (repoType == RepositoryType.DOCKER.name || repoType == RepositoryType.OCI.name) { + Criteria.where(TPackageVersion::manifestPath.name).inValues(fullPaths) + } else { + Criteria.where(TPackageVersion::artifactPath.name).inValues(fullPaths) + } + } + } + + companion object { + private val CHECKSUM_FIELDS = arrayOf( + TNode::sha256.name, + TNode::md5.name + ) + } +} diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionMetadataRuleInterceptor.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionMetadataRuleInterceptor.kt new file mode 100644 index 0000000000..78eab2aef7 --- /dev/null +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionMetadataRuleInterceptor.kt @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.tencent.bkrepo.repository.search.packages + +import com.tencent.bkrepo.common.query.model.Rule +import com.tencent.bkrepo.repository.dao.PackageVersionDao +import com.tencent.bkrepo.repository.search.common.MetadataRuleInterceptor +import org.springframework.stereotype.Component + +/** + * 版本元数据规则拦截器 + */ +@Component +class VersionMetadataRuleInterceptor( + override val packageVersionDao: PackageVersionDao, + private val metadataRuleInterceptor: MetadataRuleInterceptor +) : VersionRuleInterceptor(packageVersionDao) { + + override fun match(rule: Rule) = metadataRuleInterceptor.match(rule) + override fun getVersionCriteria(rule: Rule, context: PackageQueryContext) = + metadataRuleInterceptor.intercept(rule, context) +} diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionNameRuleInterceptor.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionNameRuleInterceptor.kt new file mode 100644 index 0000000000..fcd5ffe8e8 --- /dev/null +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionNameRuleInterceptor.kt @@ -0,0 +1,79 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.tencent.bkrepo.repository.search.packages + +import com.tencent.bkrepo.common.api.exception.ErrorCodeException +import com.tencent.bkrepo.common.api.message.CommonMessageCode +import com.tencent.bkrepo.common.query.enums.OperationType +import com.tencent.bkrepo.common.query.model.Rule +import com.tencent.bkrepo.repository.dao.PackageVersionDao +import com.tencent.bkrepo.repository.model.TPackageVersion +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.stereotype.Component + +/** + * 版本号规则拦截器 + */ +@Component +class VersionNameRuleInterceptor( + override val packageVersionDao: PackageVersionDao +) : VersionRuleInterceptor(packageVersionDao) { + + override fun match(rule: Rule): Boolean { + return rule is Rule.QueryRule && rule.field == "version" + } + + override fun getVersionCriteria(rule: Rule, context: PackageQueryContext): Criteria { + with(rule as Rule.QueryRule) { + val versionQueryRule = when (operation) { + OperationType.IN -> + rule.copy(field = TPackageVersion::name.name, value = (value as List<*>).map { it.toString() }) + + in SUPPORT_OPERATIONS -> rule.copy(field = TPackageVersion::name.name, value = value.toString()) + else -> throw ErrorCodeException( + CommonMessageCode.METHOD_NOT_ALLOWED, + "$field only support ${SUPPORT_OPERATIONS.map { it.name }} operation type." + ) + }.toFixed() + return context.interpreter.resolveRule(versionQueryRule, context) + } + } + + companion object { + private val SUPPORT_OPERATIONS = arrayOf( + OperationType.EQ, + OperationType.IN, + OperationType.MATCH, + OperationType.MATCH_I + ) + } +} diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionRuleInterceptor.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionRuleInterceptor.kt new file mode 100644 index 0000000000..80679b7f0a --- /dev/null +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/packages/VersionRuleInterceptor.kt @@ -0,0 +1,91 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.tencent.bkrepo.repository.search.packages + +import com.tencent.bkrepo.common.mongo.dao.AbstractMongoDao.Companion.ID +import com.tencent.bkrepo.common.mongo.dao.util.Pages +import com.tencent.bkrepo.common.query.enums.OperationType +import com.tencent.bkrepo.common.query.interceptor.QueryContext +import com.tencent.bkrepo.common.query.interceptor.QueryRuleInterceptor +import com.tencent.bkrepo.common.query.model.Rule +import com.tencent.bkrepo.repository.dao.PackageVersionDao +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.data.mongodb.core.query.Query + +/** + * 版本条件规则拦截器 + * 1. 将传入规则转换为package_version表的查询条件 + * 2. 将version查询结果转换为packageId查询规则, 作为package查询的筛选条件 + */ +abstract class VersionRuleInterceptor( + open val packageVersionDao: PackageVersionDao +) : QueryRuleInterceptor { + + abstract fun getVersionCriteria(rule: Rule, context: PackageQueryContext): Criteria + + override fun intercept(rule: Rule, context: QueryContext): Criteria { + require(context is PackageQueryContext) + // 查找符合条件的version + val versionQuery = Query(getVersionCriteria(rule, context)) + val versionMap = queryRecords(versionQuery) { query -> packageVersionDao.find(query) } + .groupBy({ it.packageId }, { it.name }) + // 多个版本查询规则在同一个package的版本号交集 + for ((key, value) in versionMap) { + context.matchedVersions.putIfAbsent(key, value.toMutableSet())?.retainAll(value.toSet()) + } + val emptyKeys = context.matchedVersions.filterValues { it.isEmpty() }.keys + // 构建packageId查询规则 + val packageIdList = (versionMap.keys - emptyKeys).toList() + val newRule = if (packageIdList.size == 1) { + Rule.QueryRule(ID, packageIdList.first(), OperationType.EQ) + } else { + Rule.QueryRule(ID, packageIdList, OperationType.IN) + } + return context.interpreter.resolveRule(newRule.toFixed(), context) + } + + protected fun queryRecords(query: Query, execFind: (Query) -> List): List { + val records = mutableListOf() + var pageNumber = 1 + do { + val pageRequest = Pages.ofRequest(pageNumber, PAGE_SIZE) + val page = execFind(query.with(pageRequest)) + records.addAll(page) + pageNumber++ + } while (page.size == PAGE_SIZE) + return records + } + + companion object { + const val PAGE_SIZE = 1000 + } +} diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/software/packages/SoftwarePackageSearchInterpreter.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/software/packages/SoftwarePackageSearchInterpreter.kt index 69168cf60b..681c1dc152 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/software/packages/SoftwarePackageSearchInterpreter.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/search/software/packages/SoftwarePackageSearchInterpreter.kt @@ -34,7 +34,6 @@ package com.tencent.bkrepo.repository.search.software.packages import com.tencent.bkrepo.common.query.builder.MongoQueryInterpreter import com.tencent.bkrepo.common.query.interceptor.QueryContext import com.tencent.bkrepo.common.query.model.QueryModel -import com.tencent.bkrepo.repository.search.common.MetadataRuleInterceptor import com.tencent.bkrepo.repository.search.common.SelectFieldInterceptor import com.tencent.bkrepo.repository.search.packages.PackageQueryContext import com.tencent.bkrepo.repository.search.software.interceptor.SoftwareModelValidateInterceptor @@ -56,7 +55,6 @@ class SoftwarePackageSearchInterpreter( addModelInterceptor(SelectFieldInterceptor()) addRuleInterceptor(softwareRepoTypeRuleInterceptor) addRuleInterceptor(softwareRepoNameRuleInterceptor) - addRuleInterceptor(MetadataRuleInterceptor()) } override fun initContext(queryModel: QueryModel, mongoQuery: Query): QueryContext { diff --git a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/service/packages/impl/PackageServiceImpl.kt b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/service/packages/impl/PackageServiceImpl.kt index 8fc6d82b2b..0839ca844c 100644 --- a/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/service/packages/impl/PackageServiceImpl.kt +++ b/src/backend/repository/biz-repository/src/main/kotlin/com/tencent/bkrepo/repository/service/packages/impl/PackageServiceImpl.kt @@ -41,6 +41,7 @@ import com.tencent.bkrepo.common.artifact.constant.ARTIFACT_INFO_KEY import com.tencent.bkrepo.common.artifact.message.ArtifactMessageCode import com.tencent.bkrepo.common.artifact.repository.context.ArtifactContextHolder import com.tencent.bkrepo.common.artifact.repository.context.ArtifactDownloadContext +import com.tencent.bkrepo.common.mongo.dao.AbstractMongoDao.Companion.ID import com.tencent.bkrepo.common.mongo.dao.util.Pages import com.tencent.bkrepo.common.query.model.QueryModel import com.tencent.bkrepo.common.security.util.SecurityUtils @@ -60,6 +61,7 @@ import com.tencent.bkrepo.repository.pojo.packages.request.PackagePopulateReques import com.tencent.bkrepo.repository.pojo.packages.request.PackageUpdateRequest import com.tencent.bkrepo.repository.pojo.packages.request.PackageVersionCreateRequest import com.tencent.bkrepo.repository.pojo.packages.request.PackageVersionUpdateRequest +import com.tencent.bkrepo.repository.search.packages.PackageQueryContext import com.tencent.bkrepo.repository.search.packages.PackageSearchInterpreter import com.tencent.bkrepo.repository.util.MetadataUtils import com.tencent.bkrepo.repository.util.PackageEventFactory @@ -401,11 +403,15 @@ class PackageServiceImpl( } override fun searchPackage(queryModel: QueryModel): Page> { - val context = packageSearchInterpreter.interpret(queryModel) + val context = packageSearchInterpreter.interpret(queryModel) as PackageQueryContext val query = context.mongoQuery val countQuery = Query.of(query).limit(0).skip(0) val totalRecords = packageDao.count(countQuery) - val packageList = packageDao.find(query, MutableMap::class.java) + val packageList = packageDao.find(query, MutableMap::class.java) as List> + packageList.forEach { + val packageId = it[ID].toString() + context.matchedVersions[packageId]?.apply { it[MATCHED_VERSIONS] = this } + } val pageNumber = if (query.limit == 0) 0 else (query.skip / query.limit).toInt() return Page(pageNumber + 1, query.limit, totalRecords, packageList) } @@ -486,6 +492,7 @@ class PackageServiceImpl( companion object { private val logger = LoggerFactory.getLogger(PackageServiceImpl::class.java) + private const val MATCHED_VERSIONS = "matchedVersions" private fun convert(tPackage: TPackage?): PackageSummary? { return tPackage?.let { diff --git a/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/NodeSearchServiceTest.kt b/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/NodeSearchServiceTest.kt index aa9840bf9d..df872dd011 100644 --- a/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/NodeSearchServiceTest.kt +++ b/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/NodeSearchServiceTest.kt @@ -51,6 +51,7 @@ import com.tencent.bkrepo.repository.pojo.node.service.NodeCreateRequest import com.tencent.bkrepo.repository.pojo.repo.RepoCreateRequest import com.tencent.bkrepo.repository.pojo.search.NodeQueryBuilder import com.tencent.bkrepo.repository.search.common.LocalDatetimeRuleInterceptor +import com.tencent.bkrepo.repository.search.common.MetadataRuleInterceptor import com.tencent.bkrepo.repository.search.common.RepoNameRuleInterceptor import com.tencent.bkrepo.repository.search.common.RepoTypeRuleInterceptor import com.tencent.bkrepo.repository.search.node.NodeQueryInterpreter @@ -82,7 +83,8 @@ import java.time.format.DateTimeFormatter NodeQueryInterpreter::class, RepoNameRuleInterceptor::class, RepoTypeRuleInterceptor::class, - LocalDatetimeRuleInterceptor::class + LocalDatetimeRuleInterceptor::class, + MetadataRuleInterceptor::class ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class NodeSearchServiceTest @Autowired constructor( diff --git a/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/query/NodeQueryInterpreterTest.kt b/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/query/NodeQueryInterpreterTest.kt index 3ff965dcc0..41a0f9d8bc 100644 --- a/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/query/NodeQueryInterpreterTest.kt +++ b/src/backend/repository/biz-repository/src/test/kotlin/com/tencent/bkrepo/repository/service/query/NodeQueryInterpreterTest.kt @@ -35,6 +35,7 @@ import com.tencent.bkrepo.common.query.model.Sort import com.tencent.bkrepo.repository.pojo.search.NodeQueryBuilder import com.tencent.bkrepo.repository.pojo.stage.ArtifactStageEnum import com.tencent.bkrepo.repository.search.common.LocalDatetimeRuleInterceptor +import com.tencent.bkrepo.repository.search.common.MetadataRuleInterceptor import com.tencent.bkrepo.repository.search.common.RepoNameRuleInterceptor import com.tencent.bkrepo.repository.search.common.RepoTypeRuleInterceptor import com.tencent.bkrepo.repository.search.node.NodeQueryInterpreter @@ -64,6 +65,9 @@ class NodeQueryInterpreterTest : ServiceBaseTest() { @MockBean private lateinit var localDateTimeRuleInterceptor: LocalDatetimeRuleInterceptor + @MockBean + private lateinit var metadataRuleInterceptor: MetadataRuleInterceptor + @BeforeAll fun beforeAll() { initMock() @@ -83,7 +87,8 @@ class NodeQueryInterpreterTest : ServiceBaseTest() { permissionManager, repoNameRuleInterceptor, repoTypeRuleInterceptor, - localDateTimeRuleInterceptor + localDateTimeRuleInterceptor, + metadataRuleInterceptor ) val query = interpreter.interpret(queryModel) println(query.queryModel) @@ -104,7 +109,8 @@ class NodeQueryInterpreterTest : ServiceBaseTest() { permissionManager, repoNameRuleInterceptor, repoTypeRuleInterceptor, - localDateTimeRuleInterceptor + localDateTimeRuleInterceptor, + metadataRuleInterceptor ) val query = interpreter.interpret(queryModel) println(query.queryModel)