使用 Spring 数据 MongoDB 从 MongoDB 中的嵌入式数组中查找包含元素子列表的实体

Find entities containing a sublist of elements from an embedded array in MongoDB with Spring Data MongoDB

我有一个 MongoDB 实体,它有一个标签列表:

@Document
@TypeAlias("project")
data class Project(@Id var id: String?,
                   val name: String,
                   val tags: MutableList<Tag>)

我想查找包含标签子集的项目。

例如给定这些项目:

projectService.save(Project(null, "someProject11",  
    mutableListOf(Tag("area","IT"), Tag("department","Architecture"))))

projectService.save(Project(null, "someProject12", 
    mutableListOf(Tag("area","IT"), Tag("department","HR"))))

如果我按如下方式定义存储库:

interface ProjectRepository : ReactiveCrudRepository<Project, String> {
    fun findByTags(tags : List<Tag>): Flux<Project>
}

寻找子集不起作用,例如:Tag("area","IT") 的项目应该 return 两个结果但实际上 returns 0。底层的 mongo 查询是:

{"find": "project", "filter": {"tags": [{"key": "area", "value": "IT"}]}

它只适用于传递列表的完整内容listOf(Tag("area","IT"), Tag("department","Architecture")):

{"find": "project", "filter": {"tags": [{"key": "area", "value": "IT"},{"key": "department", "value": "Architecture"}]}

如何查询包含列表子集的实体?

使用 Criteria$elemMatch 运算符解决:

interface CustomProjectRepository {
    fun findByTags(tags: List<Tag>): Flux<Project>
}

class CustomProjectRepositoryImpl(private val mongoTemplate: ReactiveMongoTemplate) : CustomProjectRepository {
    override fun findByTags(tags: List<Tag>): Flux<Project> {
        val query = Query()
        val criterias = mutableListOf<Criteria>()
        tags.forEach {
            criterias.add(Criteria.where("tags").elemMatch(Criteria.where("key").`is`(it.key).and("value").`is`(it.value)))
        }
        query.addCriteria(Criteria().andOperator(* criterias.toTypedArray()))
        return mongoTemplate.find(query, Project::class.java)
    }
}

interface ProjectRepository : ReactiveCrudRepository<Project, String>, CustomProjectRepository {

    fun findByClientIdAndId(clientId: String, id: String): Mono<Project>
    fun findByClientId(clientId: String): Flux<Project>
}