#c# #mongodb #.net-core
#c# #mongodb #.net-core
Вопрос:
У меня есть приложение, которое записывает данные в MONGODB.
В документе у меня есть поле с именем updatedOn. В этом я пишу datetime в строковом формате, как показано ниже:
DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
Я знаю, что мне следовало использовать только тип даты, сейчас это хранится в базе данных в виде строки.
Теперь я получил требование фильтровать данные на основе этого поля между двумя датами.
Скажите что-то вроде этого :
Дата начала: «01/01/2019»
Дата окончания: «31/01/2019»
Это код, который я использовал ниже (который не работает)
IMongoCollection<Order> OrderCollection = GetOrderCollection();
List<OrderFilter> lstJobs;
FilterDefinitionBuilder<Order> OrderFilter = Builders<Order>.Filter;
DateTime start = Convert.ToDateTime("01/01/2019");
DateTime end = Convert.ToDateTime("31/01/2019");
var filter = OrderFilter.Gte("UpdatedOn", start) amp;
OrderFilter.Lt("UpdatedOn", end);
var fields = Builders<Order>.Projection.Include(p => p.Id);
lstOrders = await OrderCollection.Find(filter).Project<OrderFilter>(fields).ToListAsync<OrderFilter>().ConfigureAwait(false);
Класс OrderFilter:
public class OrderFilter
{
[DataMember(Name = "id")]
public string Id { get; set; }
}
Класс заказа:
public class Order
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "UpdatedOn")]
public string UpdatedOn { get; set; }
}
Поскольку updatedOn является строкой, и уже были вставлены некоторые данные. Это нецелесообразно изменять.
Кто-нибудь может помочь мне выполнить фильтрацию в этом случае. Есть ли какие-либо типизации или преобразования, которые я могу выполнить в самом коде и выполнить фильтрацию.
Большое спасибо!
Комментарии:
1. для начала измените
DateTime start = Convert.ToDateTime("01/01/2019");
наDateTime start = Convert.ToDateTime("2019/01/01")
, чтобы избежать неоднозначности дня и месяца2. @JohnB Я сделал. Хотя это не помогло
Ответ №1:
Вам нужно будет проанализировать строку по дате, чтобы иметь возможность сравнивать с ней другие даты. Смотрите документы здесь.
Чтобы иметь возможность делать это на C #, вам придется использовать агрегированный метод, подобный этому:
DateTime start = Convert.ToDateTime("01/01/2019");
DateTime end = Convert.ToDateTime("31/01/2019");
var projectionDefinition =
Builders<BsonDocument>.Projection.Exclude("convertedDate");
OrderCollection.Aggregate().AppendStage<BsonDocument>("{ $addFields: {convertedDate: { $toDate: '$UpdatedOn' }}}").Match(
Builders<BsonDocument>.Filter.Gte(x => x["convertedDate"], new BsonDateTime(start))
amp; Builders<BsonDocument>.Filter.Lte(x => x["convertedDate"], new BsonDateTime(end)))
.Project(projectionDefinition).As<Order>();
Вероятно, вы сможете сделать это намного красивее, используя этапы.
Например,
var projectionDefinition = Builders<BsonDocument>.Projection.Exclude("convertedDate");
var expression = new BsonDocument(new List<BsonElement>
{
new BsonElement("convertedDate", new BsonDocument(new BsonElement("$toDate", "$UpdatedOn")))
});
var addFieldsStage = new BsonDocument(new BsonElement("$addFields", expression));
var gteFilter = Builders<BsonDocument>.Filter.Gte(x => x["convertedDate"], new BsonDateTime(startDate));
var lteFilter = Builders<BsonDocument>.Filter.Lte(x => x["convertedDate"], new BsonDateTime(endDate));
var combinedFilter= Builders<BsonDocument>.Filter.And(gteFilter, lteFilter);
var result = coll.Aggregate().AppendStage<BsonDocument>(addFieldsStage).Match(combinedFilter).Project(projectionDefinition).As<Order>();
И если вы добавите [BsonIgnoreExtraElements]
выше своего класса, вы сможете отказаться от этапа проектирования.
Или в вашем случае, вероятно, просто замените его проекцией, которую вы используете в данный момент, и установите .As<Type>
соответствующим образом.