我有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));
答案 0 :(得分:0)
很明显, $elemMatch(query) 是一种查询方法,用于在数组元素与查询匹配时获取数据!
您想要的是 $elemMatch(projection) !但是根据official document,此预测存在问题:
$ 运算符和 $ elemMatch 运算符都投影第一个 根据条件匹配数组中的元素。
这意味着您将只获得第一个与query匹配的元素, 所以可能不符合您的需求!
有2种方法:
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);
}
}
也许很难理解我在这段代码上写的内容,您需要检查以下链接:
答案 1 :(得分:0)
$elemMatch投影运算符不能与2级嵌套数组一起使用。从嵌套数组的第二层获取匹配数组元素的方法是使用Aggregation Pipleline,如下所示:
db.collection.aggregate( [
{ $unwind: "$productList.products" },
{ $unwind: "$productList.products.plans" },
{ $match: { "productList.products.plans.type": "G" } },
] )
这将转换为以下 Java 代码:
MongoClient mongoClient = MongoClients.create("mongodb://localhost/");
MongoDatabase database = mongoClient.getDatabase("test");
MongoCollection<Document> collection = database.getCollection("collection");
List<Bson> pipeline = Arrays.asList(
unwind("$productList.products"),
unwind("$productList.products.plans"),
match(eq("productList.products.plans.type", "G"))
);
List<Document> results = new ArrayList<>();
collection.aggregate(pipeline).into(results);
results.forEach(doc -> System.out.println(doc.toJson()));