Статьи

Использование доменных объектов C # для определения представлений Couchbase

Клиентская библиотека Couchbase 1.2-Beta включает новый API для базового управления кластером. Существуют методы для создания, удаления и вывода списка. Существуют похожие методы управления проектной документацией. Эти новые функции находятся в новом классе CouchbaseCluster в пространстве имен Couchbase.Management . Основным преимуществом этого нового API является то, что теперь вы можете позволить вашему приложению создавать свои корзины и задавать свои проектные документы при запуске. 

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

Недавно у меня появилась идея создать простую утилиту командной строки, чтобы использовать эти методы управления документами проектирования для автоматизации создания базовых представлений. Результат этой идеи находится на GitHub по адресу https://github.com/jzablocki/couchbase-model-views . Используя эту платформу, вы сможете автоматизировать создание представлений, просто украсив существующие классы модели пользовательскими атрибутами. 

Рассмотрим класс Beer со свойствами для Name, Description, Brewery и ABV. 

public class Beer
{
    public string Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public float ABV { get; set; }

    public string Brewery { get; set; }
}

Этот класс отображается на «пивные» документы в вашем ведре Couchbase. 

{
   "name": "Samuel Adams Summer Ale",
   "abv": 5.2,
   "type": "beer",
   "brewery_id": "110f04db06",
   "description": "Bright and citrusy, brewed with mysterious grains of...
}

Для достижения этого сопоставления вы, вероятно, будете использовать Newtonsoft . Атрибуты отображения свойств Json

public class Beer
{
    public string Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("abv")]
    public float ABV { get; set; }

    [JsonProperty("breweryId")]
    public string Brewery { get; set; }
}

Используя два новых атрибута, найденных в проекте CouchbaseModelViews.Framework , вы можете дополнительно украсить этот класс, чтобы объявить, какие свойства в этом классе должны быть проиндексированы Couchbase Server. Этими атрибутами являются CouchbaseDesignDocument и CouchbaseViewKey .

[CouchbaseDesignDoc("beers", "beer")]
public class Beer
{
    public string Id { get; set; }

    [JsonProperty("name")]
    [CouchbaseViewKey("by_abv_and_name", "name", 1)]
    [CouchbaseViewKey("by_name", "name")]
    public string Name { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("abv")]
    [CouchbaseViewKey("by_abv_and_name", "abv", 0)]
    public float ABV { get; set; }

    [JsonProperty("breweryId")]
    [CouchbaseViewKey("by_brewery", "breweryId")]
    public string Brewery { get; set; }
}

CouchbaseDesignDoc атрибут устанавливается на модели класса. Он использует обычный старый объект CLR (POCO) для определения проектного документа. Если вы опустите аргумент name, будет создан проектный документ с тем же именем (в нижнем регистре), что и класс. Если вы опустите аргумент типа, представления проверят, что документы имеют свойство типа со значением имени (в нижнем регистре) класса. 

CouchbaseViewKey атрибут устанавливается на свойства в классе POCO , которые должны быть проиндексированы. Например, свойство Name в классе Beer выше имеет атрибут CouchbaseViewKey с аргументами «by_name» и «name». Представление, которое будет следовать из этих значений, выглядит следующим образом:

function(doc, meta) {
  if (doc.type == "beer" && doc.name) {
     emit(doc.name, null);
  }
}

Аргумент «by_name» — это имя этого представления, а аргумент «name» определяет, какое свойство проверяется на наличие и испускается.

Также возможно включить составные ключи, украсив несколько свойств с помощью атрибутов CouchbaseViewKey, содержащих одно и то же значение для параметра viewName. Составные ключи демонстрируются с помощью «by_abv_and_name» в свойствах ABV и Name. Также обратите внимание, что существует необязательный параметр порядка, который позволяет вам установить порядок, в котором будут выбраны свойства. 

function(doc, meta) {
     if (doc.type == "beer" && doc.abv && doc.name) {
         emit([doc.abv, doc.name], null);
     }
 }

После того, как вы украсили свой класс соответствующими атрибутами, вы можете использовать проект CouchbaseModelViewsGenerator для запуска моделей через генератор представлений. Это простой проект командной строки, для которого требуется файл app.config с разделом, в котором перечислены все сборки, содержащие модели, которые будут использоваться для создания представлений.

<sectionGroup name="modelViews">
  <section name="assemblies" type="System.Configuration.DictionarySectionHandler"/>      
</sectionGroup>

<modelViews>
    <assemblies>
      <add key="DemoModels" value="CouchbaseModelViews.DemoModels" />
    </assemblies>
</modelViews>

Кроме того, вам нужно будет настроить CouchbaseClusterЭкземпляры CouchbaseCluster создаются с использованием той же конфигурации (code или app.config), что и существующий CouchbaseClient . Однако теперь есть два дополнительных свойства, которые вы можете установить для предоставления учетных данных администратора. 

<couchbase>
    <servers bucket="default" bucketPassword="" username="Administrator" password="qwerty">
        <add uri="http://localhost:8091/pools" />
    </servers>    
</couchbase>

После того как вы настроите свой app.config, убедитесь, что у вас есть перечисленные сборки в каталоге bin, куда они могут быть загружены. Самый простой способ достичь этой способности — это, конечно, ссылаться на них. Однако, если вы просто хотите использовать скомпилированную версию консольного приложения, просто скопируйте их в каталог bin.

При выполнении фреймворк создаст документ дизайна «пива», который выглядит следующим образом:

{
  "views": {
    "by_abv_and_name": {
      "map": "function(doc, meta) { \r\n\t if (doc.type == \"beer\" && doc.abv && doc.name) { \r\n\t\t emit([doc.abv, doc.name], null); \r\n\t } \r\n }"
    },
    "by_name": {
      "map": "function(doc, meta) { \r\n\t if (doc.type == \"beer\" && doc.name) { \r\n\t\t emit(doc.name, null); \r\n\t } \r\n }"
    },
    "by_brewery": {
      "map": "function(doc, meta) { \r\n\t if (doc.type == \"beer\" && doc.breweryId) { \r\n\t\t emit(doc.breweryId, null); \r\n\t } \r\n }"
    }
  }
}

Консоль не содержит никакой реальной логики создания представления. Он просто управляет вызовами различных компонентов сантехники внутри проекта Framework . Если вы предпочитаете включить создание представления в Global.asax или в другое событие запуска приложения, вы можете просто сделать эти вызовы самостоятельно. Есть четыре основных компонента структуры. 

  • ConfigParser просто считывает список сборок из раздела конфигурации и генерирует перечислимый список сборок. 
  • Класс ViewBuilder принимает сборку или перечисляемый список сборок и выполняет итерации по каждому из типов. Для каждого типа, найденного с атрибутом CouchbaseDesignDoc , создаются представления. Построить метод ViewBuilder возвращает словарь, где ключи являются именами дизайна ИХ и значения являются фактическими проектными документами. 
  • DesignDocManager принимает словарь с именем дока, паром DOC дизайна и использует CouchbaseCluster для создания проектной документации. 
  • Есть также класс ViewRunner , который будет запускать вновь созданные представления.
    var assemblies = ConfigParser.GetAssemblies();
    var builder = new ViewBuilder();
    builder.AddAssemblies(assemblies.ToList());
    var designDocs = builder.Build();
    var ddManager = new DesignDocManager();
    ddManager.Create(designDocs, (s) => Console.WriteLine("Created {0} design doc", s));
    var runner = new ViewRunner();
    runner.Run(designDocs, (k, v, s) => Console.WriteLine("[{0}::{1}] Key {2}", k, v, s["key"]), 5);

Между этими двумя компонентами нет связи, и вы можете использовать их по своему усмотрению. Если у вас есть собственное средство сбора сборок, например, просто передайте его в ViewBuilder.Build, чтобы отобразить JSON, необходимый для создания представлений. 

На данный момент фреймворк в основном завершен и достаточно протестирован. В коде есть несколько циклов, чем я хотел бы, и я мог бы использовать Tuples слишком много, но это работает. Не стесняйтесь использовать его в своих проектах. Имейте в виду, что это проект Couchbase Labs, и он официально не поддерживается. Помните также, что она использует бета-версию .NET Couchbase Client Library и API может быть изменен.