Средние значения хэш-таблицы MongoDB

Я использую С# вместе с MongoDB. У меня есть класс, который может быть похож на это. Это образец, который что-то представляет, пожалуйста, не комментируйте дизайн класса.

[CollectionName("Venues")]
public class Venue
{
   public string Name { get; set; }
   public dictionary<string,object> Properties { get; set; }
}

var venue = new Venue
{
  Name = "Venue 1",
  Properties = new Dictionary<string,object>
  {
    { "Chairs", "18" },
    { "Tables", "4" },
    { "HasWaterfall", true }
  }
}

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

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

2: Определить среднее значение одного элемента в базе данных. Например, по всем записям я хотел бы вычислить среднее стулья, опять же не загружая все записи, а затем делая это в памяти с помощью линк и тд....

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В основном ваш образец документа сохраняется как JSON ниже:

{
    "_id" : ObjectId("..."),
    "Name" : "Venue 1",
    "Properties" : {
            "Chairs" : "18",
            "Tables" : "4",
            "HasWaterfall" : true
    }
}

Это дает вам возможность определить проекцию, используя запись через точку:

var filter = Builders<Venue>.Filter.Eq(f => f.Name, "Venue 1");
var projection = Builders<Venue>.Projection.Include("Properties.Chairs");

List<BsonDocument> data = Col.Find(filter).Project(projection).ToList();

который возвращает нижеследующий BsonDocument:

{ "_id" : ObjectId("..."), "Properties" : { "Chairs" : "18" } }

Чтобы получить среднее значение, вам нужно использовать оператор $toInt, представленный в MongoDB 4.0, для преобразования ваших значений из строки в целое число. Пытаться:

var project = new BsonDocument()
{
    { "chairs", new BsonDocument() { { "$toInt", "$Properties.Chairs" } } }
};

var group = new BsonDocument()
{
    { "_id", "null" },
    { "avg", new BsonDocument() { { "$avg", "$chairs" }  } }
};

var avg = Col.Aggregate().Project(project).Group(group).First();

Блестящий ответ и объяснение, спасибо. Я вижу, что он отлично работает в версии 4, я ограничен версией 3.6, Azure Cosmos DB, но я попытаюсь найти другую реализацию для $toInt, которой не существует. Еще действительно отличный ответ.

Louis Lewis 29.05.2019 21:20

вот альтернативный способ сделать это с помощью удобной библиотеки MongoDB.Entities.

using System.Collections.Generic;
using System.Linq;
using MongoDB.Entities;

namespace StackOverflow
{
    class Program
    {
        [Name("Venues")]
        public class Venue : Entity
        {
            public string Name { get; set; }
            public Dictionary<string, object> Properties { get; set; }
        }

        static void Main(string[] args)
        {
            new DB("test");

            var venue1 = new Venue
            {
                Name = "Venue 1",
                Properties = new Dictionary<string, object>  {
                    { "Chairs", 28 },
                    { "Tables", 4 },
                    { "HasWaterfall", true }
                }
            };
            venue1.Save();

            var venue2 = new Venue
            {
                Name = "Venue 2",
                Properties = new Dictionary<string, object>  {
                    { "Chairs", 38 },
                    { "Tables", 4 },
                    { "HasWaterfall", true }
                }
            };
            venue2.Save();

            var chairs = DB.Find<Venue, object>()
                           .Match(v => v.Name == "Venue 1")
                           .Project(v => new { ChairCount = v.Properties["Chairs"] })
                           .Execute();

            var avgChairs = DB.Collection<Venue>()
                              .Average(v => (int)v.Properties["Chairs"]);

        }
    }
}

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

получение стульев в зале 1:

db.runCommand({
    "find": "Venues",
    "filter": {
        "Name": "Venue 1"
    },
    "projection": {
        "Properties.Chairs": NumberInt("1"),
        "_id": NumberInt("0")
    },
    "$db": "test"
})

получение среднего количества стульев по всем площадкам:

db.Venues.aggregate([
    {
        "$group": {
            "_id": NumberInt("1"),
            "__result": {
                "$avg": "$Properties.Chairs"
            }
        }
    }
])

Другие вопросы по теме

Похожие вопросы