簡體   English   中英

Spring Boot Data和MongoDB - 過濾子文檔數組查詢

[英]Spring Boot Data and MongoDB - Filter Subdocument Array Query

我試圖使用Spring來查詢Mongo存儲庫並過濾數組子文檔。 我已經引用了如何使用mongodb過濾子文檔中的數組 ,但是想知道是否有更合適的或java結構化的方法來使用Spring。

我目前正在使用速記存儲庫接口表示法,但我正在使用未過濾的數組返回完整的文檔。

PersonRepository.java

@Repository
public interface PersonRepository extends MongoRepository <Person, String> {
    List<Person> findByAddressZipCode(@Param("zip") int zip);
}

Person.java

@Document
public class Person {
    @Id
    private String id;

    private String firstName;
    private String lastName;
    private List<Address> address;
}

Address.java

public class Address {
    private int zip;
}

樣本輸入

{
 "firstName":"George",
 "lastName":"Washington",
 "address":[{
     "zip":"12345"
  },{
     "zip":"98765"
  },{
     "zip":"12345"
  }]
}

預期產出

{
 "firstName":"George",
 "lastName":"Washington",
 "address":[{
     "zip":"12345"
  },{
     "zip":"12345"
  }]
}

實際產出

{
 "firstName":"George",
 "lastName":"Washington",
 "address":[{
     "zip":"12345"
  },{
     "zip":"98765"
  },{
     "zip":"12345"
  }]
}

那么,在Spring Data中,這種查詢並不trivial

壞消息:
Spring Data Repository沒有MongoDB Aggregation解決方案。 所以,你不能在MongoRepository中實現任何方法,比如aggregateBy...

好消息:
Spring Data提供了MongoTemplate類,允許您執行復雜查詢,就像在標准MongoDB shell中一樣。

因此,由於您只想exclude與某些條件不匹配的子文檔,我們需要定義聚合pipelines

我假設:

zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter

MongoDB聚合將是:

db.person.aggregate([
    {$unwind: "$address"},
    {$match: {"address.zip": 12345}},
    {$group: { _id: { "firstName":"$firstName", "lastName":"$lastName", _id:"$_id" }, address: { $push: "$address" } } },
    {$project: {_id:0, "firstName":"$_id.firstName", "lastName":"$_id.lastName", "address": "$address"}}
])

如果所有過濾器都成功,我們得到:

[ 
    {
        "address" : [ 
            {
                "zip" : 12345
            }, 
            {
                "zip" : 12345
            }
        ],
        "firstName" : "George",
        "lastName" : "Washington"
    }
]


現在,以Spring Data方式,您需要在項目中添加一些更改:

首先,找到你需要添加的mongo-config.xml

 <!-- Define the mongoDbFactory with your database Name --> <mongo:db-factory uri="mongodb://user:pass@localhost:27017/db"/> <!-- Define the MongoTemplate --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </bean> 

MongoTemplate是Spring的MongoDB支持的中心類,提供與數據庫交互的功能集。 模板...提供域對象MongoDB文檔之間的映射。 更多信息

其次,在@Service類中,添加以下代碼以加載到@PostConstruct

 @Autowired private MongoOperations mongoOperations; ... public List<Person> findByAddressZipCode(int zip) { List<AggregationOperation> list = new ArrayList<AggregationOperation>(); list.add(Aggregation.unwind("address")); list.add(Aggregation.match(Criteria.where("address.zip").is(zip))); list.add(Aggregation.group("firstName", "lastName").push("address").as("address")); list.add(Aggregation.project("firstName", "lastName", "address")); TypedAggregation<Person> agg = Aggregation.newAggregation(Person.class, list); return mongoOperations.aggregate(agg, Person.class, Person.class).getMappedResults(); } 

注意: PersonAddress都應該有默認的空構造函數!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM