Как мне вернуть документ mongo, элемент которого находится в массиве?

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

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

Вопрос:

У меня есть следующий документ в коллекции mongodb под названием «Элементы»

 "_id": {
        "$oid": "5fcfa614d588d46ec44cc375"
    },
    "ProductId": {
        "$binary": {
            "base64": "LredEr/ 9UGY3g5oIDWhPw==",
            "subType": "03"
        }
    },
    "ProductName": "ModelProductTest",
    "AccountId": {
        "$binary": {
            "base64": "Gzmr JvFq0y0YRBOfkj57w==",
            "subType": "03"
        }
    },
    "Skus": [
        {
            "_id": {
                "$oid": "5fcfa614d588d46ec44cc376"
            },
            "ProductSkuId": {
                "$binary": {
                    "base64": "MBLj5bL6C0Cph0fMkpbDZA==",
                    "subType": "03"
                }
            },
            "ProductId": {
                "$binary": {
                    "base64": "LredEr/ 9UGY3g5oIDWhPw==",
                    "subType": "03"
                }
            },
            "SkuCode": "kkss",
            "Barcode": "12345",
            "Description": "test",
            "StockQuantity": {
                "$numberInt": "2"
            },
            "Costs": [
                {
                    "_id": {
                        "$oid": "5fcfa614d588d46ec44cc378"
                    },
                    "ProductPriceId": {
                        "$binary": {
                            "base64": "81rqEsKc9k6y2IQQjE1DJg==",
                            "subType": "03"
                        }
                    },
                    "ProductSkuId": {
                        "$binary": {
                            "base64": "MBLj5bL6C0Cph0fMkpbDZA==",
                            "subType": "03"
                        }
                    },
                    "DateValidFrom": {
                        "$date": {
                            "$numberLong": "1607443988489"
                        }
                    },
                    "Cost": "33"
                },
                {
                    "_id": {
                        "$oid": "5fcfa614d588d46ec44cc379"
                    },
                    "ProductPriceId": {
                        "$binary": {
                            "base64": "aqdf9S6yUUCIZEjLY/1pvw==",
                            "subType": "03"
                        }
                    },
                    "ProductSkuId": {
                        "$binary": {
                            "base64": "MBLj5bL6C0Cph0fMkpbDZA==",
                            "subType": "03"
                        }
                    },
                    "DateValidFrom": {
                        "$date": {
                            "$numberLong": "1607443988492"
                        }
                    },
                    "Cost": "39"
                }
            ]
        },
        {
            "_id": {
                "$oid": "5fcfa614d588d46ec44cc377"
            },
            "ProductSkuId": {
                "$binary": {
                    "base64": "XFkTknYw2Uyy2ae/F/yj1A==",
                    "subType": "03"
                }
            },
            "ProductId": {
                "$binary": {
                    "base64": "LredEr/ 9UGY3g5oIDWhPw==",
                    "subType": "03"
                }
            },
            "SkuCode": "kksass",
            "Barcode": "12346",
            "Description": "test",
            "StockQuantity": {
                "$numberInt": "6"
            },
            "Costs": [
                {
                    "_id": {
                        "$oid": "5fcfa614d588d46ec44cc37a"
                    },
                    "ProductPriceId": {
                        "$binary": {
                            "base64": "hxWucmMsnkOkRb1j9/EtGA==",
                            "subType": "03"
                        }
                    },
                    "ProductSkuId": {
                        "$binary": {
                            "base64": "XFkTknYw2Uyy2ae/F/yj1A==",
                            "subType": "03"
                        }
                    },
                    "DateValidFrom": {
                        "$date": {
                            "$numberLong": "1607443988492"
                        }
                    },
                    "Cost": "31"
                },
                {
                    "_id": {
                        "$oid": "5fcfa614d588d46ec44cc37b"
                    },
                    "ProductPriceId": {
                        "$binary": {
                            "base64": "ExyZdI6suE2Zs5oRdeiK9w==",
                            "subType": "03"
                        }
                    },
                    "ProductSkuId": {
                        "$binary": {
                            "base64": "XFkTknYw2Uyy2ae/F/yj1A==",
                            "subType": "03"
                        }
                    },
                    "DateValidFrom": {
                        "$date": {
                            "$numberLong": "1607443988492"
                        }
                    },
                    "Cost": "36"
                }
            ]
        }
    ]
 

Я хочу, чтобы при поиске по штрих-коду возвращался основной объект и конкретный артикул (не все артикулы). Как мне сделать это на C #, используя драйвер mongo?

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

1. Вы что-нибудь пробовали? Это просто выглядит как JSON. Вы должны иметь возможность читать / анализировать его практически без проблем, используя C #.

2. Извините, я не совсем ясно выразился. Я пытаюсь извлечь его из mongo. Я не хочу извлекать весь документ, поскольку он потенциально может быть огромным. Я изменил свой вопрос, чтобы сделать его немного более понятным, что мне нужно сделать.

Ответ №1:

вы можете легко сделать это с AsQueryable помощью интерфейса официального драйвера следующим образом:

 collection.AsQueryable()
          .Where(i => i.Skus.Any(s => s.Barcode == "22222222")))
          .Select(i => new Item
          {
              Id = i.Id,
              ProductName = i.ProductName,
              Skus = i.Skus.Where(s => s.Description == "second sku")
          })
          .ToListAsync();
 

вам нужно выполнить ручную проекцию для каждого свойства основного объекта, который вам нужно вернуть, и просто отфильтровать артикулы с Where помощью предложения.

вышеуказанное будет переведено в конвейер агрегации следующим образом:

 [
    {
        "$match": {
            "Skus": {
                "$elemMatch": {
                    "Barcode": "22222222"
                }
            }
        }
    },
    {
        "$project": {
            "_id": "$_id",
            "ProductName": "$ProductName",
            "Skus": {
                "$filter": {
                    "input": "$Skus",
                    "as": "s",
                    "cond": {
                        "$eq": [
                            "$s.Barcode",
                            "22222222"
                        ]
                    }
                }
            }
        }
    }
]
 

протестируйте программу с использованием mongodb.entities:

 using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using MongoDB.Entities;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace TestApplication
{
public class Item : Entity
{
    public string ProductName { get; set; }
    public IEnumerable<Sku> Skus { get; set; }
}

public class Sku
{
    [ObjectId]
    public string Id { get; set; }
    public string Barcode { get; set; }
}

public static class Program
{
    private static async Task Main()
    {
        await DB.InitAsync("test");

        await new Item
        {
            ProductName = "test product",
            Skus = new[] {
                new Sku { Id = ObjectId.GenerateNewId().ToString(), Barcode = "11111111" },
                new Sku { Id = ObjectId.GenerateNewId().ToString(), Barcode = "22222222" },
                new Sku { Id = ObjectId.GenerateNewId().ToString(), Barcode = "33333333" }
            }
        }.SaveAsync();

        var item = await DB.Queryable<Item>()
                           .Where(i => i.Skus.Any(s => s.Barcode == "22222222"))
                           .Select(i => new Item
                           {
                               ID = i.ID,
                               ProductName = i.ProductName,
                               Skus = i.Skus.Where(s => s.Barcode == "22222222")
                           })
                           .ToListAsync();
    }
}
} 

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

1. Это здорово. Однако мне нужно найти товар по штрих-коду в артикуле. Если я сделаю это, я получу обратно объект sku, а не родительский. var d = _database . getCollection<Item>(«ProductItemModels»); d.AsQueryable<Item>() .Где(i => i.Артикулы . Где (s => s.Barcode == barcode). Выберите(i => новый тем { }));

2. @coolblue2000 я обновил свой ответ. .AsQueryable().Where(i => i.Skus.Any(s => s.Barcode == "22222222"))) это фильтр, который вы ищете.

3. Спасибо. У меня новая проблема с жалобами на строку «Skus = i.Skus. Где (s => s.Barcode == «22222222»)» Он не примет его, поскольку Sku — это список, но он также не позволит мне выполнить для него ToList(). — ‘Результат операции MongoDB.Driver.Linq. Выражения. ResultOperators.ListResultOperator не поддерживается. ‘

4. Исправлено. Теперь у меня есть Sku = (List<StockPointProductSku>) i.Sku. Где(s => s.Barcode == «22222222»)»

5. Спасибо за вашу помощь.