You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB多条件数组过滤与按fieldName聚合查询需求(Scala/Java)

MongoDB多条件过滤聚合解决方案

现有集合结构

[
  {
    "_id": ObjectId("6451529ad254d565bd12156b"),
    "contentType": "Json",
    "fieldName": "xxx",
    "method": "GET",
    "value": "Car"
  },
  {
    "_id": ObjectId("6451529ad254d565bd12156d"),
    "contentType": "Json",
    "fieldName": "xxx",
    "method": "GET",
    "value": "Plane"
  },
  {
    "_id": ObjectId("6451529ad254d565bd121570"),
    "contentType": "Json",
    "fieldName": "yyy",
    "method": "GET",
    "value": "Smile"
  },
  {
    "_id": ObjectId("6451529ad254d565bd12156b"),
    "contentType": "Empty",
    "fieldName": "zzz",
    "method": "POST",
    "value": "Train"
  },
  {
    "_id": ObjectId("6451529ad254d5651112156b"),
    "contentType": "Empty",
    "fieldName": "zzz",
    "method": "POST",
    "value": "Player"
  },
  {
    "_id": ObjectId("6451529ad254d565bd12156d"),
    "contentType": "Empty",
    "fieldName": "zzz",
    "method": "POST",
    "value": "Van"
  },
  {
    "_id": ObjectId("6451529ad254d565bd121570"),
    "contentType": "Json",
    "fieldName": "name4",
    "method": "GET",
    "value": "Van"
  }
]

需求说明

传入包含多个条件对象的数组,每个条件由method、contentType、fieldName三个字段的组合构成。需要:

  1. 过滤出符合任一条件组合的文档
  2. 按method+contentType+fieldName的组合分组,将每组的value字段聚合为数组
  3. 返回结构与请求条件一致的结果,新增聚合后的values数组字段

请求示例

[
  {
    "method": "GET",
    "contentType": "Json",
    "fieldName": "xxx"
  },
  {
    "method": "POST",
    "contentType": "Empty",
    "fieldName": "zzz"
  }
]

期望结果示例

[
  {
    "method": "GET",
    "contentType": "Json",
    "fieldName": "xxx",
    "values": ["Car", "Plane"]
  },
  {
    "method": "POST",
    "contentType": "Empty",
    "fieldName": "zzz",
    "values": ["Player", "Train", "Van"]
  }
]

无效聚合语句说明

之前尝试的聚合语句存在两个核心问题:

  1. 仅能匹配单一条件,无法处理多条件数组的场景
  2. 分组逻辑错误,未按三个字段的组合分组,也没有正确收集value字段
db.collection.aggregate([
  {$match: {"$and": [{method: "GET"}, {contentType: 'Json'}, {fieldName: "xxx"}]}},
  {$group: {values: "$fieldName"}}
])

Scala 解决方案(基于Mongo Scala Driver)

import org.mongodb.scala._
import org.mongodb.scala.model.Aggregates._
import org.mongodb.scala.model.Filters._
import org.mongodb.scala.model.Projections._
import scala.concurrent.Await
import scala.concurrent.duration._

// 请求条件数据类
case class Condition(method: String, contentType: String, fieldName: String)
// 返回结果数据类
case class Result(method: String, contentType: String, fieldName: String, values: List[String])

object MongoAggregationDemo extends App {
  // 初始化Mongo客户端
  val mongoClient = MongoClient("mongodb://localhost:27017")
  val db = mongoClient.getDatabase("your_db_name")
  val collection = db.getCollection("your_collection_name")

  // 模拟传入的请求条件
  val requestConditions = List(
    Condition("GET", "Json", "xxx"),
    Condition("POST", "Empty", "zzz")
  )

  // 构建多条件匹配的$or过滤器
  val matchFilter = or(
    requestConditions.map(cond => and(
      equal("method", cond.method),
      equal("contentType", cond.contentType),
      equal("fieldName", cond.fieldName)
    ))
  )

  // 构建聚合管道
  val pipeline = Seq(
    match(matchFilter),
    // 按三个字段组合分组,收集对应value到数组
    group(
      Document("method" -> "$method", "contentType" -> "$contentType", "fieldName" -> "$fieldName"),
      push("values", "$value")
    ),
    // 投影成目标结构,展开分组的_id字段并移除原_id
    project(Document(
      "method" -> "$_id.method",
      "contentType" -> "$_id.contentType",
      "fieldName" -> "$_id.fieldName",
      "values" -> 1,
      "_id" -> 0
    ))
  )

  // 执行聚合并转换结果
  val result = Await.result(
    collection.aggregate(pipeline).toFuture(),
    10.seconds
  ).map(doc => Result(
    doc.getString("method"),
    doc.getString("contentType"),
    doc.getString("fieldName"),
    doc.getList("values", classOf[String]).toList
  ))

  // 输出结果
  result.foreach(println)

  // 关闭客户端
  mongoClient.close()
}

Java 解决方案(基于Mongo Java Driver)

import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
import static com.mongodb.client.model.Accumulators.push;

public class MongoAggregationDemo {
    // 请求条件类
    static class Condition {
        String method;
        String contentType;
        String fieldName;

        Condition(String method, String contentType, String fieldName) {
            this.method = method;
            this.contentType = contentType;
            this.fieldName = fieldName;
        }
    }

    // 返回结果类
    static class Result {
        String method;
        String contentType;
        String fieldName;
        List<String> values;

        Result(String method, String contentType, String fieldName, List<String> values) {
            this.method = method;
            this.contentType = contentType;
            this.fieldName = fieldName;
            this.values = values;
        }

        @Override
        public String toString() {
            return "Result{" +
                    "method='" + method + '\'' +
                    ", contentType='" + contentType + '\'' +
                    ", fieldName='" + fieldName + '\'' +
                    ", values=" + values +
                    '}';
        }
    }

    public static void main(String[] args) {
        // 初始化Mongo客户端(try-with-resources自动关闭)
        try (var mongoClient = MongoClients.create("mongodb://localhost:27017")) {
            MongoDatabase db = mongoClient.getDatabase("your_db_name");
            MongoCollection<Document> collection = db.getCollection("your_collection_name");

            // 模拟传入的请求条件
            List<Condition> requestConditions = List.of(
                    new Condition("GET", "Json", "xxx"),
                    new Condition("POST", "Empty", "zzz")
            );

            // 构建多条件匹配的$or过滤器
            List<Document> orFilters = new ArrayList<>();
            for (Condition cond : requestConditions) {
                orFilters.add(Filters.and(
                        Filters.eq("method", cond.method),
                        Filters.eq("contentType", cond.contentType),
                        Filters.eq("fieldName", cond.fieldName)
                ));
            }
            Document matchStage = Aggregates.match(Filters.or(orFilters));

            // 分组阶段:按三个字段组合分组,收集value数组
            Document groupStage = Aggregates.group(
                    new Document("method", "$method")
                            .append("contentType", "$contentType")
                            .append("fieldName", "$fieldName"),
                    push("values", "$value")
            );

            // 投影阶段:调整结构,展开分组的_id字段并移除原_id
            Document projectStage = Aggregates.project(Projections.fields(
                    Projections.computed("method", "$_id.method"),
                    Projections.computed("contentType", "$_id.contentType"),
                    Projections.computed("fieldName", "$_id.fieldName"),
                    Projections.include("values"),
                    Projections.excludeId()
            ));

            // 执行聚合并转换结果
            List<Result> results = new ArrayList<>();
            for (Document doc : collection.aggregate(List.of(matchStage, groupStage, projectStage))) {
                results.add(new Result(
                        doc.getString("method"),
                        doc.getString("contentType"),
                        doc.getString("fieldName"),
                        doc.getList("values", String.class)
                ));
            }

            // 输出结果
            results.forEach(System.out::println);
        }
    }
}

内容的提问来源于stack exchange,提问作者VitalyT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:45:03