Спецификация плохой проекции .NET MongoDB

#c# #.net #mongodb #mongodb-.net-driver

#c# #.net #mongodb #mongodb-.net-driver

Вопрос:

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

         var orgsUnitReadModels = _readModelService.Queryable<OrganisationalUnitReadModel>()
            .Where(x => locations.Contains(x.Id))
            .Select(x => new AuditLocationItemViewModel
            {
                Id = x.Id,
                Name = x.Name,
                AuditRecordId = auditRecordId,
                Type = type,
                IsArchived = !x.IsVisible,
                AuditStatus = auditStatus
            }).ToList();
  

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

MongoDB.Driver.MongoCommandException: Ошибка агрегирования команды: спецификация плохой проекции, не удается исключить поля, отличные от _id, в проекции включения: { Id: «$_id», Name: «$Name», AuditRecordId: BinData (3, 5797FCCCA90C8644B4CB84FED4236D4B), Тип: 0, Архивировано: { $not: [ «$isVisible» ] }, AuditStatus: 2, _id: 0 }.’

Ответ №1:

В этом примере оператор выбора LINQ преобразуется в $ project в MongoDB. Обычно вы используете 0 (или false ) для исключения полей и 1 или true для включения полей в конечный набор результатов. Конечно, вы также можете использовать синтаксис dollar для ссылки на существующие поля, что происходит, например, для Name .

Проблема в том, что вы также пытаетесь включить некоторые значения констант в памяти как часть проекции. К сожалению, один из них ( type ) равен 0 , который интерпретируется так, как если бы вы хотели исключить вызываемое поле Type из результата конвейера.

Из-за этой неоднозначности MongoDB ввел оператор $literal, и вы можете попробовать следующий синтаксис в оболочке Mongo:

 db.col.aggregate([{ $project: { _id: 0, Id: 1, Name: 1, Type: { $literal: 0 } } }])
  

Он будет возвращен 0 как постоянное значение, как вы ожидаете. В документации по драйверу MongoDB .NET здесь упоминается literal, но, похоже, это работает только для строк.

Есть несколько способов решить вашу проблему, я думаю, что проще всего сначала запустить более простую .Select инструкцию, а затем использовать .ToList() , чтобы убедиться, что запрос выполнен. Как только это будет сделано, вы можете запустить другой файл в памяти, .Select() чтобы создать свой OrganisationalUnitReadModel :

 .Where(x => locations.Contains(x.Id))
.Select(x => new { x.Id, x.Name, x.IsVisible }).ToList()
.Select(x => new AuditLocationItemViewModel
{
    Id = x.Id,
    Name = x.Name,
    Type = type,
    IsArchived = !x.IsVisible,
    AuditStatus = auditStatus
}).ToList();