Как посчитать размер массива в mongodb

К

Привет, сегодня я расскажу как можно посчитать размер массива в монгобд, и так же суммировать количество элементов в массивах.

Посчитать количество элементов в массиве

Для того, чтобы посчитать количество элементов в массиве в mongo, необходимо воспользоваться aggregation pipeline.

Давайте сначала определимся с нашей структурой данных. Допустим, мы хотим посчитать, сколько всего студентов учится на первом курсе в университете, у нас будет всего три группы, и мы хотим подсчитать количество элементов в массиве students. У нас есть следующие данные в коллекции:

[{
    "_id" : NumberLong(1),
    "students" : [ 
        1, 
        2, 
        3, 
        4
    ],
    "course" : NumberLong(1),
},
{
    "_id" : NumberLong(2),
    "students" : [ 
        5, 
        6, 
        7, 
        8,
        9,
        10,
        11
    ],
    "course" : NumberLong(1),
},
{
    "_id" : NumberLong(3),
    "students" : [ 
        12,
        13,
        14
    ],
    "course" : NumberLong(1),
}]

То есть, в первой группе 4 человека, вто второй 7, в третьей 3, в итоге у нас 14 человек на первом курсе.

Посчитаем сумму элементов в массиве

Давайте посчитаем, сколько студентов в каждой группе, для этого воспользуемся aggregation pipeline, и добавим projection stage:

{
  $project: {
    _id: 0,
    students_count: {
      $size: "$students"
    },
  }
}

Мы получим вывод:

[
  {
    "students_count": 4
  },
  {
    "students_count": 7
  },
  {
    "students_count": 3
  }
]

Мы получили сколько человек в каждой группе, теперь мы хотим получить, сколько человек всего на первом курсе. Для этого добавим еще один стейдж, который называется group:

{
  $group: {
    _id: null,
    students_total: {
      $sum: "$students_count"
    },
  }
}

Итоговый монго пайплайн

В итоге мы имеем следующий монго пайплайн:

{
  $project: {
    _id: 0,
    students_count: {
      $size: "$students"
    },
  }
}, {
  $group: {
    _id: null,
    students_total: {
      $sum: "$students_count"
    },
  }
}

Мы получим вывод:

[
  {
    "_id": null,
    "students_total": 14
  }
]

В итоге, у нас на первом курсе учится 14 человек.

Возможные ошибки

Иногда, вы можете столкнуться с проблемой:

The argument to $size must be an array, but was of type: missing

Это значит, что в каком то документе нет массива students, решается это просто, необходимо в стейдж projection добавить $ifNull, выглядеть это будет так:

{
  $project: {
    _id: 0,
    students_count: {
       $size: {"$ifNull": [ "$students", [] ]}
    },
  }
}

Проблема решена!

Код для Java

Код для Java выглядит так:

import java.util.Arrays;
import org.bson.Document;
import org.bson.BsonNull;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.conversions.Bson;
import java.util.concurrent.TimeUnit;
import org.bson.Document;

/*
 * Requires the MongoDB Java Driver.
 * https://mongodb.github.io/mongo-java-driver
 */

MongoClient mongoClient = new MongoClient(
    new MongoClientURI("YOU_MONGO_URL")
);
MongoDatabase database = mongoClient.getDatabase("univer");
MongoCollection<Document> collection = database.getCollection("groups");

FindIterable<Document> result = collection.aggregate(Arrays.asList(new Document("$project", 
    new Document("_id", 0L).append("students_count", 
    new Document("$size", 
    new Document("$ifNull", Arrays.asList("$students", Arrays.asList()))))), 
    new Document("$group", 
    new Document("_id", new BsonNull()).append("students_total", 
    new Document("$sum", "$students_count")))));

Код пайплайна вы можете найти здесь

Автор

Denis Pershin

Добавить комментарий