我遇到需要从MongoDB中的集合查询结果的情况。我想使用$ group基于一个字段聚合我的集合。但我想在结果中留下那些剩余的字段,但不在这些字段上应用任何聚合函数,如($ first,$ sum等)。这些剩余的字段应该在数组中。
Example: My collection:
-------------------------------------------------------------------------
| name | age | sex | province | city| area | address |
-------------------------------------------------------------------------
| A | 22 | m | Manglr | p1 | c1 | a1 |
| A | 22 | m | Kolkt | p2 | c2 | a2 |
| B | 24 | m | Mumb | p3 | c3 | a3 |
| B | 24 | m | Koch | p4 | c4 | a4 |
| B | 24 | m | Hydrbd | p5 | c5 | a5 |
-------------------------------------------------------------------------
Result I want: ($group by 'name' field only)
[
{
"name" : “A”,
"province" : [“Manglr", ‘Kolkt’]
"city" : [“p1”, ‘p2’],
"area" : [“c1”, ‘c2’],
"address" : [“a1”, ‘a2’],
},
{
"name" : “B”,
"province" : [“Mumb", ‘Koch’, 'Hydrbd']
"city" : [“p3”, ‘p4’,”p5”],
"area" : [“c3”, ‘c4’,”c5”],
"address" : [“a3”, ‘a4’,’a5’],
}
]
Please anyone help me to create a Mongo Query or Java code
答案 0 :(得分:1)
你可以尝试这样的事情。根据需要对其他字段进行分组和推送。
aggregate([{
"$group": {
"_id": "$name",
"province": {
$push: {
"key": "$province"
}
},
"city": {
$push: {
"key": "$city"
}
},
"area": {
$push: {
"key": "$area"
}
},
"address": {
$push: {
"key": "$address"
}
}
}
}, {
"$project": {
"_id": 0,
"name": "$_id",
"province": "$province.key",
"city": "$city.key",
"area": "$area.key",
"address": "$address.key"
}
}])
示例输出:
{ "province" : [ "Manglr", "kokat" ], "city" : [ "p1", "p2" ], "area" : [ "c1", "c2" ], "address" : [ "a1", "a2" ], "name" : "A" }
{ "province" : [ "Mumb", "Koch" ], "city" : [ "p3", "p4" ], "area" : [ "c3", "c4" ], "address" : [ "a3", "a4" ], "name" : "B" }
答案 1 :(得分:0)
我不知道MongoDB的方式,但以下是你可以做的Java。
package com.grs.stackOverFlow.pack05;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
class UserAccumulated{
private String name;
private List<String> city;
private List<Integer> age;
private List<Character> sex;
public UserAccumulated(){
city=new ArrayList<>();
age=new ArrayList<>();
sex=new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getCity() {
return city;
}
public void setCity(List<String> city) {
this.city = city;
}
public List<Integer> getAge() {
return age;
}
public void setAge(List<Integer> age) {
this.age = age;
}
public List<Character> getSex() {
return sex;
}
public void setSex(List<Character> sex) {
this.sex = sex;
}
public void addAge(Integer age2) {
age.add(age2);
}
public void addCity(String city2) {
city.add(city2);
}
public void addSex(Character sex2) {
sex.add(sex2);
}
public String toString(){
return String.format("{name:%s,cities : %s, sex: %s, age: %s}", name,city,sex,age);
}
}
public class User {
private String name,city;
private Integer age;
private Character sex;
public User(String name, String city, Integer age, Character sex) {
super();
this.name = name;
this.city = city;
this.age = age;
this.sex = sex;
}
public static void main(String...args){
//create a sample list ..you have to replace with code to retrieve data from mongo db
List<User> rows = Arrays.asList(new User("A", "Manglr", 22, 'm'),
new User("A", "Manglr", 22, 'm'),
new User("B", "addad", 22, 'm'),
new User("C", "addsadad", 22, 'm'),
new User("C", "sadd", 21, 'm'));
//aggregating
List<UserAccumulated> result=new ArrayList<>();
//parallestream if many records else use stream
Map<String, List<User>> map = rows.parallelStream().collect(Collectors.groupingBy(User::getName));
for(Entry<String, List<User>> entry: map.entrySet()){
UserAccumulated userA=new UserAccumulated();
userA.setName(entry.getKey());
for(User user : entry.getValue()){
userA.addAge(user.getAge());
userA.addCity(user.getCity());
userA.addSex(user.getSex());
}
result.add(userA);
}
for(UserAccumulated a: result)
System.out.println(a);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Character getSex() {
return sex;
}
public void setSex(Character sex) {
this.sex = sex;
}
}
输出如下:
{ name: A,cities : [Manglr, Manglr], sex: [m, m], age: [22, 22]} {name:B,cities : [addad], sex: [m], age: [22]} {name:C,cities : [addsadad, sadd], sex: [m, m], age: [22, 21]}
我没有把你的所有专栏用来保持简单。我不确定它与您的实际数据量的运行速度有多快。但如果性能问题让我知道。