mongodb - 如何根据嵌入式数组过滤文档?

标签 mongodb mongodb-query mongo-java mongo-java-driver

审核后this page ,特别是这个查询

db.scores.find(
   { results: { $elemMatch: { $gte: 80, $lt: 85 } } }
)

我使用了以下导入

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.elemMatch;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.excludeId;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;

并想出了以下代码来执行类似的操作 (ARRAY_FIELD_NAME = "myArray")

MongoCollection<Document> collection = mongoDB.getCollection(COLLECTION_NAME);

Bson filters = and(eq("userId", userId), elemMatch(ARRAY_FIELD_NAME, eq("id", id)));
Bson projections = fields(include(ARRAY_FIELD_NAME), excludeId());

List<Document> results = (List<Document>) collection.find(filters).projection(projections).first().get(ARRAY_FIELD_NAME);
if (CollectionUtils.isEmpty(results)) {
    return null;
}
if (results.size() > 1) {
    throw new ApiException(String.format("Multiple results matched (User ID: %s, Array item ID: %s)", userId, id));
}
return results.get(0);

过滤具有以下结构的文档

{
    "_id": {
        "$oid": "588899721bbabc26865f41cc"
    },
    "userId": 55,
    "myArray": [
        {
            "id": "5888998e1bbabc26865f41d2",
            "title": "ABC"
        },
        {
            "id": "5888aaf41bbabc3200e252aa",
            "title": "ABC"
        }
    ]
}

但不是从 myArray 字段中获取单个项或不获取任何项,我总是同时获取两个项!

唯一对我有用的代码如下

MongoCollection<Document> collection = mongoDB.getCollection(COLLECTION_NAME);

List<Bson> aggregationFlags = new ArrayList<>();
aggregationFlags.add(new Document("$unwind", "$" + ARRAY_FIELD_NAME));
aggregationFlags.add(new Document("$match", new Document("userId", userId).append(ARRAY_FIELD_NAME + ".id", id)));
aggregationFlags.add(new Document("$project", new Document("_id", 0).append(ARRAY_FIELD_NAME, "$" + ARRAY_FIELD_NAME)));

return (Document) collection.aggregate(aggregationFlags).first().get(ARRAY_FIELD_NAME);

那么为什么第一段代码的行为应该与问题开头显示的查询相同,而不是按预期过滤结果?

我不需要“聚合”结果,我需要使用用户 ID 和数组项目 ID 来“过滤”它们。

最佳答案

您需要使用 $elemMatch(projection) .像下面这样的东西应该可以工作。

import static com.mongodb.client.model.Projections.elemMatch;

Bson filters = and(eq("userId", userId));
Bson projections = fields(elemMatch(ARRAY_FIELD_NAME, eq("id", id)), excludeId());

关于mongodb - 如何根据嵌入式数组过滤文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41854801/

相关文章:

node.js - 使用 populate 查询两个模式

mongodb - 使用 java 或简单查询比较 mongodb 中的两个集合

javascript - 根据主键和外键组合两个数组

python - Mongo集合查询和运算符

mongodb - 使用 MongoEngine 排序?

node.js - 与数组相比,如何检索 mongodb 中嵌入文档的一部分?

node.js - Mongoose - 聚合添加 'is_self' 字段

mongodb - 对子数组文档执行 $sort

java - 我可以使用 JNDI 共享 MongoClient 实例吗?

mongodb - 如何为副本集启动身份验证 - MongoDB