我有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,此投影存在一个问题:


$运算符和$ elemMatch运算符都将投影第一个
根据条件匹配数组中的元素。


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

有两种方法:

1-在您的应用程序端投影所需的数据,也许使用java流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 - $ elemMatch使用Java对嵌套数组进行过滤,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60743947/

10-09 05:29