使用 Mongo 模板在 Spring Boot 中过滤内部 Arraylist 项的 Mongo 查询
Posted
技术标签:
【中文标题】使用 Mongo 模板在 Spring Boot 中过滤内部 Arraylist 项的 Mongo 查询【英文标题】:Mongo query to filter inner Arraylist items in Spring Boot using Mongo Template 【发布时间】:2019-11-17 05:21:47 【问题描述】:以下是我的文件:
@Document(collection = "products")
@Data
@EqualsAndHashCode
public class Product
@Id
private String id;
@Field("lang_content_list")
private List<ProductLangContent> contentList;
@Data
public static class ProductLangContent
@Field("lang")
private String lang;
我只想获得那些 contentList lang = 'en'。 lang 在内部列表中是唯一的。
注意:我使用的是 Mongotemplate
我的示例 json 是:
"_id" : ObjectId("5d2040f9f7c5ac1e9d8ef712"),
"lang_content_list" : [
"lang" : "en"
,
"lang" : "np"
]
"_class" : "com.sn.application.model.Product"
想要的查询结果是:
"_id" : ObjectId("5d2040f9f7c5ac1e9d8ef712"),
"lang_content_list" : [
"lang" : "en"
]
我尝试了几个查询但没有成功:
Aggregation aggregation = newAggregation(
project().and(filter("contentList")
.as("item")
.by(valueOf(
"item.lang")
.equalToValue(
"en")))
.as("contentList")
);
List<Product> results = mongoTemplate.aggregate(aggregation, Product.class, Product.class).getMappedResults();
输出为:contentList 为 null。
试过了:
Criteria elementMatchCriteria = Criteria.where("contentList").elemMatch(Criteria.where("lang").is("en"));
它给出了 contentList 中的所有元素。我不想要那个。我只想要内部列表中的一个对象,其中 lan = 'en' 。
非常感谢您。
试过了:
AggregationOperation match = Aggregation.match(Criteria.where("contentList.lang").is("en"));
AggregationOperation unwind = Aggregation.unwind("contentList");
AggregationOperation group = Aggregation.group("id")
.push("contentList").as("contentList");
List<AggregationOperation> operations = new ArrayList<>();
operations.add(match);
operations.add(unwind);
operations.add(match);
operations.add(group);
Aggregation aggregation = Aggregation.newAggregation(operations);
List<Product> results = mongoTemplate.aggregate(aggregation, Product.class, Product.class).getMappedResults();
System.out.println(results.get(0).getContentList() != null);
输出为:false。内部数组对象为 null。
【问题讨论】:
【参考方案1】:您的文档有一个数组字段“contentList”,它将有多个“lang”。我假设您要过滤/获取所有那些“contentList”中至少一个“lang”为“en”的文档。然后使用:
Criteria elementMatchCriteria = Criteria.where("contentList.lang").is("en"));
如果您只想要内部数组中 lang='en' 的那个对象,则需要使用聚合管道,例如:
链接:https://mongoplayground.net/p/JaJ7420i4qJ
db.collection.aggregate([
$match:
"lang_content_list.lang": "en"
,
$unwind: "$lang_content_list"
,
$match:
"lang_content_list.lang": "en"
,
$group:
"_id": "$_id",
"_class":
$first: "$_class"
,
"lang_content_list":
$push: "$lang_content_list"
])
使用最后一个group stage的原因是因为在你的object中,contentList是一个数组,所以我们需要将lang object包装成array,否则如果你可以改变返回类型object就不需要了。
在 Spring MongoTemplate 代码中:
AggregationOperation match = Aggregation.match(Criteria.where("lang_content_list.lang").is("en"));
AggregationOperation unwind = Aggregation.unwind("lang_content_list");
AggregationOperation group = Aggregation.group("_id")
.first("_class").as("_class")
.push("lang_content_list").as("lang_content_list");
List<AggregationOperation> operations = new ArrayList<>();
operations.add(match);
operations.add(unwind);
operations.add(match);
operations.add(group);
Aggregation aggregation = Aggregation.newAggregation(operations);
List<Product> results = mongoTemplate.aggregate(aggregation, Product.class, Product.class).getMappedResults();
【讨论】:
谢谢。但我只想要内部数组中的那个对象,其中 lang='en'。有没有办法过滤掉?我更新了问题以便更好地理解。 仅更新了内部数组中 lang='en' 的对象的答案 抱歉打扰了,你能更新一下我正在使用的语法 MongoTemplate 包的查询吗:org.springframework.data.mongodb.core.MongoTemplate; 嘿,非常感谢。我从您的建议中尝试了一段时间后找到了解决方案。非常感谢。 嗨,@Rajat Goel,你能再帮我一次吗?我在以下链接中发布了问题:***.com/questions/57132939/…以上是关于使用 Mongo 模板在 Spring Boot 中过滤内部 Arraylist 项的 Mongo 查询的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring Boot 在 Mongo 中存储原始 JSON
Spring Boot Starter-Web 尝试在启动时连接到 Mongo