嗨,我在使用Jongo使用$unwind运算符从“人”集合中获取地址列表时遇到问题。

如您所见,我将Person类定义如下:

public class Person {
    @Id
    private long personId;
    private String name;
    private int age;
    private List<Address> addresses;
//getters and setters


并且Address类的定义如下:

public class Address {
    private String houseNumber;
    private String road;
    private String town;
    private String postalCode;
//gettes and setters


查询非常简单:

public List<Address> getAddressByPersonId(long id) {
    List<Address> list = persons.aggregate("{$project:{addresses:1}}")
                                    .and("{$match:{_id:#}}",id)
                                    .and("{$unwind: '$addresses'}")
                                    .as(Address.class);
    return list;
}


我的收藏:

> db.persons.find()
{ "name" : "Bob", "age" : 34, "addresses" : [   {       "houseNumber" : "12",
"road" : "High Street",         "town" : "Small Town",  "postalCode" : "BC2 3DE"
 },     {       "houseNumber" : "12",   "road" : "High Street",         "town" :
 "Small Town",  "postalCode" : "BC2 3DE" } ], "_id" : NumberLong(1) }
>


我也为此进行了JUnit测试:

    @Before
    public void setUp(){
        service = new PersonServiceImpl();

        //store a person into the database (manually) before the tests
        MongoCollection persons = Database.getInstance().getCollection(CollectionNames.PERSONS);
        //create a new person
        Person p = new Person();
        p.setPersonId(1L);
        p.setName("Bob");
        p.setAge(34);
        //create two addresses for this person
        Address a = new Address();


        a.setHouseNumber("33");
        a.setRoad("Fake Road");
        a.setPostalCode("AB1 2CD");
        a.setTown("Big Town");
        p.addAddress(a);

        a.setHouseNumber("12");
        a.setRoad("High Street");
        a.setPostalCode("BC2 3DE");
        a.setTown("Small Town");
        p.addAddress(a);

        persons.save(p);
    }

    @After
    public void tearDown(){
        service = null;
    }

    @Test
    public void getAddressesByPersonIdTest(){

        List<Address> list = service.getAddressByPersonId(1L);
        for (Address item : list){
            item.print();
        }

        Assert.assertTrue(list.size() > 0);
    }
}


哪个输出

### Address: null null, null, null
### Address: null null, null, null


我不太清楚问题是什么。显然,测试不会失败(因此list.size()大于零...但显示为null)。 print()方法已经过测试并且可以工作。

我想获取两个Bob的地址,但是查询返回空对象。我想念什么吗?我应该以其他方式使用$ unwind吗?请建议

最佳答案

Aggregation Framework返回与输入格式完全相同的格式-展开后唯一的区别是addresses字段下嵌入了多少个地址。在您的情况下,您将获得两个文档:

{ "_id": 1,
  "name" : "Bob",
  "age" : 34,
  "addresses" : { "houseNumber" : "12",
                  "road" : "High Street",
                  "town" : "Small Town",
                  "postalCode" : "BC2 3DE"
  }
}


这不能非常有效地转换为Address类,因为如您所见,Address对象是addresses字段的值,而不是顶级对象。

尚不清楚的是为什么您需要进行汇总-您正在获得一个人的地址列表。当您通过ID对人员执行简单的find()时,字段“地址”已经是List对象的Address

在MongoDB find() has the option to return just selected fields中,或排除命名字段(类似于SQL的SELECT *效率不如SELECT col1,col2高效),因此,如果执行the Java equivalent of db.persons.find({filter-condition}, {"_id":0, "addresses":1}),则将返回仅包含地址列表的文档。

08-06 07:18
查看更多