Как найти последние документы из MongoDB, если они имеют одинаковое время

#java #mongodb

#java #mongodb

Вопрос:

Я пытаюсь загрузить из mongodb последние документы — документы, если они имеют одинаковую временную метку в MongoDB. Есть ли какой-нибудь способ найти последний документ или документы?

Итак, в этом примере возвращаемый документ должен быть первым и вторым.

 /* 1 */
{
    "_id" : ObjectId("5fbf852902fe571c41d07c9f"),
    "insertionTime" : ISODate("2020-11-26T10:36:25.600Z")
}

/* 2 */
{
    "_id" : ObjectId("5fbf852902fe571c41d07ca0"),
    "insertionTime" : ISODate("2020-11-26T10:36:25.600Z")
}

/* 3 */
{
    "_id" : ObjectId("5fbf852902fe571c41d07ca1"),
    "insertionTime" : ISODate("2020-11-24T10:36:25.600Z")
}

/* 4 */
{
    "_id" : ObjectId("5fbf854702fe571c41d07ca9"),
    "insertionTime" : ISODate("2020-11-23T10:36:55.582Z")
}
 

Я смог найти только последний документ, но только на пределе.

 private List<Bson> prepareFilter() {
    Bson sortByTimeFilter = sort(Sorts.descending(INSERTION_TIME));
    Bson latestFilter = limit(1);
    return Arrays.asList(sortByTimeFilter, latestFilter);
}
 

После попытки агрегировать коллекцию я получил только один документ. Конечно, благодаря пределу (1) есть только один документ. Есть ли какой-либо способ объединить N последних документов, если они имеют одинаковую временную метку?

Заранее спасибо. С наилучшими пожеланиями

Комментарии:

1. Поможет ли вам ответ?

2. @varman Прошу прощения, что не ответил раньше, я только что увидел ваш комментарий. Нет. Мне это не помогло, потому что я не мог использовать MongoTemplate :(.

Ответ №1:

Я использую MongoTemplate для агрегирования. Я рассказываю способ здесь. Автоматическое подключение MongoTemplate

@Autowired private MongoTemplate MongoTemplate;

  • $sort помогает сортировать по времени вставки
  • $group помогает найти последний объект latestDoc и одновременно поместить весь документ в массив allDocs
  • Поскольку у нас есть последний документ и весь массив документов, мы можем отфильтровать весь массив документов, используя последнюю временную метку документа,
  • $unwind для деконструкции массива (теперь allDocs массив становится объектом)
  • $replaceRoot для замены объекта на ROOT

Метод

 public List<Object> test(List<String> companies,List<String> professions ) {

    Aggregation aggregation = Aggregation.newAggregation(
        sort(Sort.Direction.DESC, "insertionTime"),
        group()
            .first("$$ROOT").as("latestDoc")
            .push("$$ROOT").as("allDocs")
        p-> new Document("$project",
                new Document("allDocs",                     
                    new Document("$filter"
                        new Document()
                        .append("input","$allDocs")                     
                        .append("cond",
                            new Document("$eq",Arrays.asList("$$this.insertionTime","$latestDoc.insertionTime"))
                        )
                    )
                                                            
            )
        ),
        unwind("allDocs"),
        replaceRoot("allDocs")

    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_COLLECTION.class), Object.class).getMappedResults();

}
 

Рабочая игровая площадка Mongo

Если вы не используете шаблон Mongo, вы можете использовать, как вы уже пробовали, или ТРЮК ДЛЯ ПРЕОБРАЗОВАНИЯ ОБОЛОЧКИ MONGO

Примечание: этот код не тестируется. Но это было написано при работе над сценарием mongo