Обновление документа с помощью игнорирования драйвера _id - PullRequest
0 голосов
/ 16 октября 2018

Я хотел бы иметь возможность обновлять пару ключ / значение в документе в коллекции без учета _id.Этот SO-ответ , по-видимому, предоставляет способ сделать то, что я хочу, но требует сосредоточенности на ключе _id.

По сути, что я могу сделать, чтобы получить мой код, как показано ниже, чтобы работать без добавления атрибута [BsonIgnoreExtraElements] в класс?

Основываясь на коде, который я покажу ниже, я думаю, что я близок, и у меня do есть возможностьОбходной путь, используя атрибут, который я также покажу.Тем не менее, я хотел бы сделать это без украшения классов с какими-либо атрибутами, если это возможно.

Почему нет _id?Лично я считаю, что поле _id просто мешает.Он не является частью какого-либо из моих классов, и MongoDB не является реляционным, поэтому я просто не использую его.Я свободно признаю, что, возможно, я полностью упускаю намерение и идею использования поля _id, но я просто не вижу необходимости в этом в MongoDB.Тем не менее, если возможно, я бы хотел сосредоточиться на работе без акцента на поле _id.

С учетом сказанного у меня есть методы для извлечения одного документа или всей коллекции вместе со вставкой одного документа илився коллекция, как правило, без учета поля _id.

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

public const string ELEMENT_ID = "_id";
ProjectionDefinition<T> projection = Builders<T>.Projection.Exclude(ELEMENT_ID);
IFindFluent<T, T> found = mongoCollection.Find(bsonDocument).Project<T>(projection);

Для справочной информации, вот метод поиска, игнорирующий _id:

public T GetSingle<T>(string property, string value) where T : class, new()
        {
            T tObject = null;
            try
            {
                if (MongoContext.MongoClient != null && MongoContext.MongoDatabase != null)
                {
                    string className = typeof(T).ToString();
                    int lastPeriod = className.LastIndexOf('.');
                    int length = className.Length - lastPeriod;
                    className = className.Substring(lastPeriod + 1, length - 1);
                    if (!string.IsNullOrEmpty(className))
                    {
                        IMongoCollection<T> mongoCollection = MongoContext.MongoDatabase.GetCollection<T>(className);
                        if (mongoCollection != null)
                        {
                            BsonDocument bsonDocument = new BsonDocument();
                            ProjectionDefinition<T> projection = Builders<T>.Projection.Exclude(ELEMENT_ID);
                            PropertyInfo[] propertyInfo = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
                            if (propertyInfo != null && propertyInfo.Length > 0)
                            {
                                IEnumerable<PropertyInfo> piExisting = propertyInfo.Where(pi => pi.Name.Equals(property, StringComparison.CurrentCultureIgnoreCase));
                                if (piExisting != null && piExisting.Any())
                                {
                                    BsonValue bsonValue = BsonValue.Create(value);
                                    BsonElement bsonElement = new BsonElement(property, bsonValue);
                                    if (bsonElement != null)
                                    {
                                        bsonDocument.Add(bsonElement);
                                    }
                                    IFindFluent<T, T> found = mongoCollection.Find(bsonDocument).Project<T>(projection);
                                    if (found != null)
                                    {
                                        tObject = found.FirstOrDefault<T>();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteToLog(Logger.LoggerMessage(ex));
            }
            return tObject;
        }

Похож на другой ответ SO , я пытался использовать FindOneAndUpdate, но получаю следующую ошибку:

Элемент '_id' не совпадаетлюбое поле или свойство класса ClassThingy.Suffix.

Если бы я мог как-то применить Проекцию к FindOneAndUpdate, я думаю, что это могло бы решить мою проблему, но я не смог найти способчтобы сделать это приложение.

Вот мой код:

public T UpdateSingle<T>(T item, string property, object originalValue, object newValue) where T : class, new()
{
    string className = string.Empty;
    T updatedDocument = null;
    try
    {
        if (MongoContext.MongoClient != null && MongoContext.MongoDatabase != null)
        {
            className = ClassUtility.GetClassNameFromObject<T>(item);
            if (!string.IsNullOrEmpty(className))
            {
                IMongoCollection<T> mongoCollection = MongoContext.MongoDatabase.GetCollection<T>(className);
                if (mongoCollection != null)
                {
                    BsonDocument bsonDocument = new BsonDocument();
                    ProjectionDefinition<T> projection = Builders<T>.Projection.Exclude(ELEMENT_ID);
                    PropertyInfo[] propertyInfo = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    if (propertyInfo != null && propertyInfo.Length > 0)
                    {
                        IEnumerable<PropertyInfo> piExisting = propertyInfo.Where(pi => pi.Name.Equals(property, StringComparison.CurrentCultureIgnoreCase));
                        if (piExisting != null && piExisting.Any())
                        {
                            BsonValue bsonValue = BsonValue.Create(originalValue);
                            BsonElement bsonElement = new BsonElement(property, bsonValue);
                            if (bsonElement != null)
                            {
                                bsonDocument.Add(bsonElement);
                            }
                            IFindFluent<T, T> found = mongoCollection.Find(bsonDocument).Project<T>(projection);
                            if (found != null)
                            {
                                FilterDefinition<T> filterDefinition = Builders<T>.Filter.Eq(property, originalValue);
                                UpdateDefinition<T> updateDefinition = Builders<T>.Update.Set(property, newValue);
                                updatedDocument = mongoCollection.FindOneAndUpdate<T>(filterDefinition, updateDefinition);
                            }
                        }
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        Logger.WriteToLog(Logger.LoggerMessage(ex));
    }
    return updatedDocument;
}

Интересно, что метод FindOneAndUpdate действительно выглядит успешным, а коллекция "Суффикс" действительно получаетмодифицирована.Кроме того, возвращение не содержит модификации.Вместо этого это «оригинал» (когда я использую обходной путь, как показано ниже).

Дополнительная информация:

Класс суффикса:

public class Suffix
{
    public string Code { get; set; }
    public string Description { get; set; }
}

enter image description here

Suffix suffix = new Suffix();
MongoRepository.MongoRepository mongoRepository = new MongoRepository.MongoRepository("MyDataBase");
mongoRepository.UpdateSingle<Suffix>(suffix, "Description", "Jr", "Junior");

Обходной путь:

[BsonIgnoreExtraElements]
public class Suffix
{
    public string Code { get; set; }
    public string Description { get; set; }
}

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

1 Ответ

0 голосов
/ 16 октября 2018

Здесь вам не хватает третьего параметра метода .FindOneAndUpdate() типа FindOneAndUpdateOptions<T,T>.Это место, где вы можете определить, хотите ли вы получить документ After или Before модификацию.Before является значением по умолчанию. Кроме того, вы можете указать проекцию и исключить _id свойство.Попробуйте:

FilterDefinition<T> filterDefinition = Builders<T>.Filter.Eq(property, originalValue);
UpdateDefinition<T> updateDefinition = Builders<T>.Update.Set(property, newValue);
ProjectionDefinition<T, T> projection = Builders<T>.Projection.Exclude("_id");
var options = new FindOneAndUpdateOptions<T>()
{
    Projection = projection,
    ReturnDocument = ReturnDocument.After
};
updatedDocument = mongoCollection.FindOneAndUpdate<T>(filterDefinition, updateDefinition, options);
...