Как отобразить массив объектов в массив свойств объекта с помощью вложенного массива MongoDB c # - PullRequest
1 голос
/ 30 апреля 2019

Я пытаюсь создать следующие методы для извлечения массива ObjectId из дочернего массива.

GetStorageLocationIds()

GetStorageRoomIds(ObjectId locationId)

GetStorageSectionIds(ObjectId locationId, ObjectId roomId)

GetStorageShelfIds(ObjectId locationId, ObjectId roomId, ObjectId sectionId)

GetStorageSlotIds(ObjectId locationId, ObjectId roomId, ObjectId sectionId, ObjectId shelfId) (это может быть не так сложно, поскольку это уже массив ObjectId)

Каждый метод должен возвращать IEnumerable<ObjectId>, содержащиймассив свойства id соответствующего массива.Я понимаю, что мог бы просто получить весь документ для каждого списка, но я бы предпочел более эффективное и элегантное решение с использованием драйвера MongoDB c #.

Это пример документа:

{
"_id" : ObjectId("5cb2271a4bd93c0dec4db163"),
...
"StorageRooms" : [
    {
        "_id" : ObjectId("5cb49adc36ad6719bf947103"),
        ...
        "StorageSections" : [ ]
    },
    {
        "_id" : ObjectId("5cb49afa36ad6719bf947106"),
        ...
        "StorageSections" : [
            {
                "_id" : ObjectId("5cb49bb8c40cd319cb2511ae"),
                ...
                "StorageShelves" : [ ]
            },
            {
                "_id" : ObjectId("5cb49bb8c40cd319cb2511af"),
                ...
                "StorageShelves" : [
                    {
                        "_id" : ObjectId("5cb49bfe8d259019d9207f48"),
                        ...
                        "StorageSlotIds" : [ ]
                    },
                    {
                        "_id" : ObjectId("5cb49bfe8d259019d9207f49"),
                        ...
                        "StorageSlotIds" : [ ]
                    }
                ]
            }
        ]
    },
    {
        "_id" : ObjectId("5cb49afa36ad6719bf947107"),
        ...
        "StorageSections" : [ ]
    }
]

}

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

GetStorageLocationIds() -> ["5cb2271a4bd93c0dec4db163"]

GetStorageRoomIds("5cb2271a4bd93c0dec4db163") -> ["5cb49adc36ad6719bf947103,"5cb49afa36ad6719bf947106", "5cb49afa36ad6719bf947107"]

GetStorageSectionIds("5cb49afa36ad6719bf947106") -> ["5cb49bb8c40cd319cb2511ae","5cb49bb8c40cd319cb2511af"]

и т. Д.

До сих пор я смог написать первый: GetStorageLocationIds.Этот код, кажется, работает хорошо:

public async Task<IEnumerable<ObjectId>> GetAllDocumentIdsAsync(string database, string collection,
        CancellationToken cancellationToken)
    {
        return (await _mongoContext.MongoClient.GetDatabase(database).GetCollection<T>(collection)
            .Find(new BsonDocument())
            .Project(new BsonDocument {{"_id", 1}})
            .ToListAsync(cancellationToken)).Select(x => x[0].AsObjectId);
    }

Когда дело доходит до следующего, я пытался использовать ProjectionDefinition, но все, что он делал, это возвращал документ id вместо каждого id вмассив StorageRooms.

public async Task<IEnumerable<ObjectId>> GetStorageRoomIdsAsync(ObjectId id, CancellationToken cancellationToken)
    {
        var filter = Builders<StorageLocation>.Filter.And(
            Builders<StorageLocation>.Filter.Where(location => location.Id == id));
        var projectionDefinition = Builders<StorageLocation>.Projection.Include(location => location.StorageRooms);

        var projectionResult = await ProjectAsync(filter, projectionDefinition, cancellationToken);
        return projectionResult.Select(x => x[0].AsObjectId);
    }

После некоторых попыток использования агрегации, я считаю, что он будет работать с Unwind, но я заблудился, как правильно реализовать это в c #.Заранее благодарим за любую помощь.

Редактировать Примечание: ObjectId и string в этом вопросе используются для краткости взаимозаменяемо.Я использую AutoMapper для моего реального проекта

Редактировать 2:

Ответ от Мики работал на GetStorageRoomIds.Я сейчас пытаюсь использовать следующий код для GetStorageSectionIds, но получаю ошибку:

return from location in AsQueryable()
            where location.Id == id
            from room in location.StorageRooms
            where room.Id == roomId
            from section in room.StorageSections 
            select section.Id;

Ошибка здесь

1 Ответ

1 голос
/ 30 апреля 2019

Для таких запросов вы можете запустить AsQueryable() на вашем IMongoCollection, а затем использовать синтаксис LINQ, как показано ниже:

var storageRoomIds = from location in Col.AsQueryable()
                     where location.Id == locationId
                     from room in location.StorageRooms
                     select room.Id;

Вы также можете включить Профилировщик MongoDB , чтобы увидетьчто он будет переведен в

"pipeline" : [
    {
        "$match" : {
            "_id" : ObjectId("5cb2271a4bd93c0dec4db163")
        }
    },
    {
        "$unwind" : "$StorageRooms"
    },
    {
        "$project" : {
            "_id" : "$StorageRooms._id"
        }
    }
],

Таким образом, у вас есть и простой код C #, и эффективный запрос MongoDB

EDIT: для уровня ниже вы все равно можете использовать синтаксис LINQ:

var rooms = from location in Col.AsQueryable()
            where location.Id == locationId
            from room in location.StorageRooms
            select new
            {
                roomId = room.Id,
                storageIds = room.StorageSections.Select(x => x.Id)
            };

var storageIds = from room in rooms
                where room.roomId == roomId
                from storageId in room.storageIds
                select storageId;


var result = storageIds.ToList();

и это переводится на:

"pipeline" : [
    {
        "$match" : {
            "_id" : ObjectId("5cb2271a4bd93c0dec4db163")
        }
    },
    {
        "$unwind" : "$StorageRooms"
    },
    {
        "$project" : {
            "roomId" : "$StorageRooms._id",
            "storageIds" : "$StorageRooms.StorageSections._id",
            "_id" : 0
        }
    },
    {
        "$match" : {
            "roomId" : ObjectId("5cb49afa36ad6719bf947106")
        }
    },
    {
        "$unwind" : "$storageIds"
    },
    {
        "$project" : {
            "storageIds" : "$storageIds",
            "_id" : 0
        }
    }
],
...