Каков наилучший способ запроса миллионов записей с агрегатной GROUP в MongoDB - PullRequest
0 голосов
/ 09 января 2020

Я хотел бы спросить, как лучше всего запросить миллионную запись с агрегатом GROUP в mongoDB. теперь у меня есть проект, который хранит журнал каждый день, и есть много записей в день для хранения

this this my do c структура

{
    "_id" : ObjectId("5dfca2db3e58065c787cf821"),
    "product_id" : 47,
    "site_id" : 404,
    "b_id" : 587,
    "domain" : "google.com",
    "updated_at" : ISODate("2019-12-20T10:30:51Z"),
    "created_at" : ISODate("2019-12-20T10:30:51Z")
}

В моем отчете я бы нравится группировать по product_id и created_at, чтобы увидеть, сколько товаров в день. ниже приведен мой мон go запрос

[
    {
        '$match': [
            'created_at': [
                '$gte' => new DateTime(startDate),
                '$lte' => new DateTime(endDate),
            ],
        ],
    },
    {
        $group: {
            _id: {
                'product_id': product_id, 
                'date': {
                    $dateToString: {
                        date: '$created_at', 
                        format: '%Y-%m-%d'
                    }
                },
                'sum': {
                    '$sum': 1
                }
            }  
        }
]

, теперь в моих коллекциях 10 миллионов записей, и для выполнения запроса потребовалось около 30sec.

с explain()

"stages" : [
    {
        "$cursor" : {
            "query" : {

            },
            "fields" : {
                "created_at" : 1,
                "product_id" : 1,
                "_id" : 0
            },
            "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "site_db.doc_47",
                "indexFilterSet" : false,
                "parsedQuery" : {

                },
                "winningPlan" : {
                    "stage" : "COLLSCAN",
                    "direction" : "forward"
                },
                "rejectedPlans" : [ ]
            }
        }
    },
    {
        "$group" : {
            "_id" : {
                "product_id" : "$product_id",
                "date" : {
                    "$dateToString" : {
                        "date" : "$created_at",
                        "format" : {
                            "$const" : "%Y-%m-%d"
                        }
                    }
                },
                "sum" : {
                    "$const" : 1
                }
            }
        }
    }
],

Я уже создаю индекс для коллекций, но он, кажется, не отличается.

Итак, мой вопрос,

  1. Можно ли сделать запрос быстрее или как мы можем улучшить мой запрос?
  2. моя структура do c хороша для хранения миллионов записей?
  3. любой инструмент, который лучше, чем mongodb?

Ответы [ 2 ]

0 голосов
/ 10 января 2020
  1. возможно ли сделать запрос быстрее или как мы можем улучшить мой запрос?

Да.

Для запроса агрегации в используйте индексы, индекс должен быть создан для полей, используемых в фильтре стадии $match. Итак, создайте индекс в поле created_at:

db.test.createIndex( { created_at: 1 } )

Запрос (с некоторыми исправлениями синтаксиса):

var startDate = ISODate("2019-12-20T10:00:00Z") , endDate = ISODate("2019-12-22T10:00:00Z")

db.test.aggregate(
[
    {
        $match: {
            created_at: {
                $gte: startDate,
                $lte: endDate,
            },
        },
    },
    {
        $group: {
            _id: {
                product_id: "$product_id", 
                date: { $dateToString: {
                               format: "%Y-%m-%d",
                               date: "$created_at"
                } }
            },
            sum: {
                $sum: 1
            }
        }
    }
] )

Если вы генерируете план запроса используя метод explain, вы увидите, что используется индекс:

"stage" : "IXSCAN"
"indexName" : "created_at_1"

И этот запрос будет более быстрым с индексом created_at.


Моя структура do c подходит для хранения миллионов записей?

В целом, в структуре документа нет проблем. Вы должны понимать, какие поля вы хотите в документе. Запросы, которые вы собираетесь выполнить в коллекции, должны указывать, какие детали должны быть в документе.


какой инструмент лучше mongodb?

Есть, может быть (сейчас у меня нет никакой информации об этом).

0 голосов
/ 09 января 2020

Я бы предложил создать другую коллекцию, в которой будет храниться только нужная вам сводка. Вы можете создать пакетное задание или потоковое приложение в реальном времени, которое заполняет эту коллекцию, вместо выполнения дорогостоящих запросов в вашем хранилище необработанных данных

...