в mongodb, какой самый эффективный способ получить первый и последний документ - PullRequest
2 голосов
/ 30 июня 2019

У меня есть такие документы:

class A
{
    DateTime T;
    ...
}

и я хотел бы найти самый ранний и самый новый документ.

Лучше ли это сделать:

        var First   = db.Collection.AsQueryable().OrderBy(_ => _.t).FirstOrDefault();
        var Last    = db.Collection.AsQueryable().OrderByDescending(_ => _.t).FirstOrDefault();

или

        var First   = db.Collection.AsQueryable().OrderBy(_ => _.t).FirstOrDefault();
        var Last    = db.Collection.AsQueryable().OrderBy(_ => _.t).LastOrDefault();

или

        var C = db.Collection.AsQueryable().OrderBy(_ => _.t);
        var First = C.FirstOrDefault();
        var Last = C.LastOrDefault();

Мне интересно, есть ли что-нибудь с базовой реализацией, которая могла бы изменить скорость между этими параметрами?

Мне интересно, если сортировка уже была сделана один раз, возможно ли, что результат кэшируется, и получение первого и последнего элементов будет быстрее?

1 Ответ

2 голосов
/ 30 июня 2019

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

db.setProfilingLevel(2)

Затем, чтобы проверить последний запрос, выполненный в базе данных, вам нужно выполнить:

db.system.profile.find().limit(1).sort( { ts : -1 } ).pretty()

Итак, за первый фрагмент кода вы получите:

"pipeline" : [ { "$sort" : { "t" : 1 }  },
               { "$limit" : 1 }
]

"pipeline" : [ { "$sort" : { "t" : -1 }  },
               { "$limit" : 1 }
]

Для второй пары он печатает

"pipeline" : [ { "$sort" : { "t" : 1 }  },
               { "$limit" : 1 }
]

и выбрасывает NotSupportedException для LastOrDefault на моем компьютере, если он работает на версии драйвера MongoDB, вы можете проверить сгенерированный оператор MongoDB с помощью профилировщика

Для последнего, когда вы наведите курсор мыши на c в вашей Visual Studio, он печатает

{aggregate([{ "$sort" : { "t" : 1 } }])}

, но поскольку он относится к типу IOrderedQueryable<T>, это не материализованный запрос, поэтому он будет выполняться в базе данных при запуске FirstOrDefault, генерирующем то же тело агрегации, что и предыдущие операторы. Я получаю NotSupportedException и здесь. Здесь вы можете найти список поддерживаемых операторов LINQ, и оба Last и LastOrDefault не реализованы, поэтому вам нужно отсортировать по убыванию.

...