java - 使用 java 的嵌套数组的 $elemMatch 过滤器

标签 java mongodb

我有 JSON

{
  "responseCode": 200,
  "productList": {
    "count": 25,
    "products": [
      {
        "id": 403492,
        "description": null,
        "plans": [
          {
            "name": "test1",
            "type": "G"
          },
          {
            "name": "test2",
            "type": "Y"
          }
        ]
      }
    ],
  }
}

我想获得仅类型“G”的计划,我不想将 test2 返回到 json 我尝试使用 $elemMatch 但不起作用

Document query = new Document();

query.append("plans", new Document().append("$elemMatch", value));

最佳答案

很明显 $elemMatch(query) 是一种查询方法,当数组的元素与查询匹配时获取数据!

你想要的是$elemMatch(projection) !但根据official document,这个投影存在问题。 :

Both the $ operator and the $elemMatch operator project the first matching element from an array based on a condition.

这意味着您将只获得与查询匹配的第一个元素, 所以也许它不符合您的需求!

有两种方法:

1-在应用程序端投影您想要的数据,也许使用 java Stream api!

2- 使用 $filter(aggregation)

第二种方式(java代码):

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.util.Arrays;

import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Filters.*;

public class Test {

public static void main(String[] args) throws Exception
{
    MongoClient client = MongoClients.create(
            "mongodb://localhost:27017"
    );

    MongoDatabase database = client.getDatabase("TEST");
    MongoCollection<Document> documentMongoCollection =
            database.getCollection("test");

    Document document = documentMongoCollection.aggregate(
            Arrays.asList(
                    match(elemMatch("productionList.products.plans" , eq("type" ,"G")))

                    ,project(new Document("productionList.products" ,
                            map("productionList.products" , "this" ,
                                    new Document("plans" ,
                                            filter("$this.plans" ,
                                                    "plan" ,
                                                    new Document(
                                                            "$eq" ,
                                                            Arrays.asList("$$plan.type" , "G")
                                                    )))
                                            .append("description" , "$$this.description")//make it present
                                            .append("id" , "$$this.id"))) //make it present
                            .append("responseCode" , 1) //include
                            .append("productionList.count" , 1) //include
            )
    )).first();



    System.out.println(document.toJson());
}


private final static Bson filter(String arrayName , String as , Bson cond)
{
    //so to do it !

    Document document = new Document("input" , "$"+arrayName);

    if(as!=null && !as.isEmpty())
        document.append("as" , as);

    document.append("cond" , cond);

    return new Document("$filter" , document);
}

private final static Bson map(String arrayName ,String as , Bson in)
{
    Document document = new Document("input" , "$"+arrayName);

    if(as!=null && !as.isEmpty())
        document.append("as" , as);

    document.append("in" , in);

    return new Document("$map" , document);
}
}

也许很难理解我在这段代码上写的内容,您需要检查以下链接:

$map(aggregation)

$expr

$project(aggregation)

关于java - 使用 java 的嵌套数组的 $elemMatch 过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60743947/

相关文章:

java - Mongodb如何查看字段的所有元素是否包含在超集中

java - 如何在聚合中映射_id参数

PHP MongoDB 与 MongoDate 上的查询结果不一致

angularjs - 直接在前端自动更新 mongodb 中的更改,无需使用 Node Socket.io 和 angularjs 刷新页面

java - 计算当前连胜 - sqlite

java - 如何正确地将数组添加到集合中?

java - WildFly 部署期间出现错误

java - maven attach-artifact - 保留原来的名字

mongodb - 使用 MongoDB 聚合管道对文档进行计数

java - Appengine 和 java.io 的使用