Este artigo foi traduzido por máquina.

O programador

Mudando para o NoSQL com o MongoDB, Parte 3

Ted Neward

Baixe o código de exemplo

Ted NewardÚltima vez, eu continuou a minha exploração de MongoDB pelo uso de testes de exploração. Eu descrito como iniciar e parar o servidor durante um teste mostrou como capturar as referências de documento de cruz e abordou algumas do raciocínio por trás do awkwardness de fazê-lo. Agora é hora de explorar mais alguns recursos de MongoDB intermediários: predicado de consultas, funções agregadas e o suporte a LINQ fornecido pelo conjunto de módulos MongoDB.Linq. Eu também fornecerá algumas observações sobre hospedagem MongoDB em um ambiente de produção.

Quando nós do último nosso Hero da esquerda. . .

Por motivos de espaço, eu não analisar grande parte dos artigos anteriores; em vez disso, lê-las on-line no pode e problemas de junho em MSDN.microsoft.com /magazine de . No pacote do código associado, no entanto, os testes de exploração tem sido elaborados check-out para incluir um conjunto de exemplo preexistente de dados para trabalhar, usando caracteres de um dos meus programas de TV favoritos. A Figura 1 mostra um teste de exploração anterior, por meio do atualizador. Até aqui, tudo bem.

Figura 1 de teste de uma exploração de exemplo

[TestMethod]
        public void StoreAndCountFamilyWithOid()
        {
          var oidGen = new OidGenerator();
          var peter = new Document();
          peter["firstname"] = "Peter";
          peter["lastname"] = "Griffin";
          peter["_id"] = oidGen.Generate();

          var lois = new Document();
          lois["firstname"] = "Lois";
          lois["lastname"] = "Griffin";
          lois["_id"] = oidGen.Generate();

          peter["spouse"] = lois["_id"];
          lois["spouse"] = peter["_id"];

          var cast = new[] { peter, lois };
          var fg = db["exploretests"]["familyguy"];
          fg.Insert(cast);

          Assert.AreEqual(peter["spouse"], lois["_id"]);
          Assert.AreEqual(
            fg.FindOne(new Document().Append("_id",
              peter["spouse"])).ToString(), lois.ToString());

          Assert.AreEqual(2,
            fg.Count(new Document().Append("lastname", "Griffin")));
        }

Chamando todas as pessoas antigas. . .

Em artigos anteriores, o código do cliente foi procurada em todos os documentos que correspondam a um critério específico (como, por exemplo, ter um campo de “ lastname ” correspondentes a uma determinada cadeia de caracteres ou um campo de “ _id ” correspondentes a uma determinada identificação de objeto), mas que ainda não discuti como fazer consultas do estilo de predicado (como “ localizar todos os documentos onde o ‘ idade ’ campo tem um valor superior a 18 ”). Acontece, MongoDB não usa uma interface semelhante à SQL para descrever a consulta para executar; em vez disso, use ECMAScript/JavaScript, e na verdade, ele pode aceitar blocos de código seja executado no servidor para o filtro ou agregação de dados quase como um procedimento armazenado.

Isso fornece alguns recursos semelhantes a LINQ, mesmo antes de examinar os recursos do LINQ suportados pelo assembly Mongo.Linq. Especificando um documento que contém um campo chamado “ $ onde ” e um bloco de código que descreve o código ECMAScript para executar consultas complexas arbitrariamente podem ser criadas:

 

[TestMethod]
        public void Where()
        {
          ICursor oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where", 
            new Code("this.gender === 'F'")));
          bool found = false;
          foreach (var d in oldFolks.Documents)
            found = true;
          Assert.IsTrue(found, "Found people");
        }

Como você pode ver, a chamada de localização retorna uma instância de ICursor, que, embora propriamente dito não é IEnumerable (o que significa que não pode ser usado no loop foreach), que contém uma propriedade de documentos é um IEnumerable <Document>. Se a consulta retornaria um conjunto muito grande de dados, o ICursor pode ser limitado para retornar os primeiros resultados de n, definindo sua propriedade de limite de n .

A sintaxe da consulta de predicado vem sabores diferentes de quatro, mostrados no do Figura 2.

A Figura 2 do quatro diferentes sintaxes de consulta de predicado

[TestMethod]
        public void PredicateQuery()
        {
          ICursor oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("age",
            new Document().Append("$gt", 18)));
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where",
            new Code("this.age > 18")));
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find("this.age > 18");
          Assert.AreEqual(6, CountDocuments(oldFolks));

          oldFolks =
            db["exploretests"]["familyguy"].Find(
            new Document().Append("$where",
            new Code("function(x) { return this.age > 18; }")));
          Assert.AreEqual(6, CountDocuments(oldFolks));
        }

Nos formulários de segundo e terceiro “ isso ” sempre faz referência ao objeto que está sendo examinado.

Você pode enviar qualquer comando arbitrário (ou seja, o código ECMAScript) por meio do driver para o banco de dados, na verdade, usando os documentos para transmitir a consulta ou comando. Assim, por exemplo, o método de contagem fornecido pela interface IMongoCollection é realmente apenas uma conveniência em todo este trecho de código mais detalhado:

[TestMethod]
        public void CountGriffins()
        {
          var resultDoc = db["exploretests"].SendCommand(
            new Document()
              .Append("count", "familyguy")
              .Append("query",
                new Document().Append("lastname", "Griffin"))
            );
          Assert.AreEqual(6, (double)resultDoc["n"]);
        }

Isso significa que qualquer uma das operações agregadas descritas pela documentação MongoDB, tais como “ distintas ” ou “ grupo ”, por exemplo, podem ser acessadas pelo mesmo mecanismo, mesmo que eles não podem ser reproduzidos como métodos em APIs de MongoDB.Driver.

Você pode enviar comandos arbitrários fora de uma consulta ao banco de dados por meio da sintaxe de “ nome especial ” “ eval, $ ”, que permite que qualquer bloco de ECMAScript legítimo do código seja executado em relação ao servidor novamente essencialmente como um procedimento armazenado:

[TestMethod]
        public void UseDatabaseAsCalculator()
        {
          var resultDoc = db["exploretests"].SendCommand(
            new Document()
              .Append("$eval", 
                new CodeWScope { 
                  Value = "function() { return 3 + 3; }", 
                  Scope = new Document() }));
          TestContext.WriteLine("eval returned {0}", resultDoc.ToString());
          Assert.AreEqual(6, (double)resultDoc["retval"]);
        }

Ou, use a função eval fornecida no banco de dados diretamente. Se isso não é flexível o suficiente, o MongoDB permite o armazenamento das funções definidas pelo usuário de ECMAScript na instância do banco de dados para execução durante as consultas e os blocos de execução do lado do servidor adicionando ECMAScript funções para a coleção de banco de dados especial “ system.js ”, conforme descrito em que o site da Web de MongoDB .

A faltando do LINQ

O driver do c# MongoDB também tem suporte a LINQ, permitindo que os desenvolvedores escrevam código de cliente MongoDB como, por exemplo, o que é mostrado no do Figura 3.

De um exemplo de suporte a LINQ, a Figura 3

[TestMethod]
        public void LINQQuery()
        {
          var fg = db["exploretests"]["familyguy"];
          var results = 
            from d in fg.Linq() 
            where ((string)d["lastname"]) == "Brown" 
            select d;
          bool found = false;
          foreach (var d in results)
          {
            found = true;
            TestContext.WriteLine("Found {0}", d);
          }
          Assert.IsTrue(found, "No Browns found?");
        }

Além disso, com a natureza dinâmica do banco de dados MongoDB, este exemplo requer sem geração de código, apenas a chamada Linq para retornar um objeto que o provedor LINQ MongoDB “ permite ”. No momento da redação deste artigo, suporte a LINQ é muito rudimentar, mas ele é aperfeiçoado e momento em que este artigo chega a impressão será significativamente melhor. Documentação dos novos recursos e exemplos, estará no wiki do site do projeto .

Remessa é um recurso

Caso contrário, acima de tudo se MongoDB a ser usado em um ambiente de produção, algumas coisas que precisa ser tratados para torná-lo menos doloroso os chaps ruins que têm de manter os servidores de produção e os serviços em execução.

Para começar, o processo do servidor (mongod.exe) deve ser instalado como um serviço — executá-lo em uma sessão da área de trabalho interativa normalmente não é permitida em um servidor de produção. Para esse fim, mongod.exe oferece suporte a uma opção de instalação do serviço “-instalar, ” que instala como um serviço, em seguida, pode ser iniciado pelo painel de serviços ou a linha de comando: “ net start MongoDB ”. No entanto, como da redação deste artigo, há uma sutileza pequena--comando de instalação — ele infere o caminho para o executável, observando a linha de comando usada para executá-lo, para que o caminho completo deverá ser fornecido na linha de comando. Isso significa que se MongoDB estiver instalado em C:\Prg\mongodb, você deve instalá-lo como um serviço em um prompt de comando (com direitos administrativos) com o comando C:\Prg\mongodb\bin\mongod.exe - instalar.

No entanto, todos os parâmetros de linha de comando, como “ – dbpath, ” deve também aparecem nesse comando de instalação, o que significa que se qualquer uma das configurações — a porta, o caminho para os arquivos de dados e assim por diante — alterar, o serviço deve ser reinstalado. Felizmente, o MongoDB suporta uma opção de arquivo de configuração fornecida pela “-config ” opção de linha de comando, portanto, normalmente a melhor abordagem é passar o caminho do arquivo config completo para a instalação do serviço e fazer tudo isso adicionais de configuração a partir daí:

C:\Prg\mongodb\bin\mongod.exe --config C:\Prg\mongodb\bin\mongo.cfg --install
net start MongoDB

Como sempre, é a maneira mais fácil de testar para garantir que o serviço está sendo executado com êxito para se conectar a ele com o cliente mongo.exe que acompanha o download de MongoDB. E, como o servidor se comunica com os clientes via soquetes, você precisa examinar os buracos necessários no firewall para permitir a comunicação entre servidores.

Eles não são Droids os dados que você está procurando

É claro que, sem segurança de acesso ao servidor MongoDB não é provável que haja algo bom, para que proteger o servidor contra visitantes indesejados torna-se um recurso-chave. MongoDB oferece suporte à autenticação, mas o sistema de segurança em qualquer lugar não é quase tão sofisticada que foi encontrado com “ ferro de passar grande ” bancos de dados, como o SQL Server.

Normalmente, a primeira etapa é criar um logon de administrador de banco de dados, conectando-se ao banco de dados com o cliente mongo.exe e adicionando um usuário administrador no banco de dados do administrador (um banco de dados que contém dados para a execução e administração de todo o servidor MongoDB), da seguinte forma:

> use admin
> db.addUser("dba", "dbapassword")

Depois de fazer isso, qualquer ação adicional, mesmo dentro deste shell, exigirão acesso autenticado, o que é feito no shell, a autenticação explícita:

> db.authenticate("dba", "dbapassword")

O DBA agora pode adicionar usuários a um banco de dados MongoDB alterando bancos de dados e adicionar o usuário usando a mesma chamada addUser mostrada anteriormente:

> use mydatabase
> db.addUser("billg", "password")

Ao se conectar ao banco de dados por meio do Mongo.Driver, passar as informações de autenticação como parte da seqüência de conexão usada para criar o objeto Mongo e a mágica de autenticação de mesmo irá ocorrer de forma transparente:

var mongo = new Mongo("Username=billg;Password=password");

Naturalmente, as senhas não devem ser codificadas diretamente no código ou armazenados abertamente; a disciplina de senha mesmo que qualquer aplicativo de backup do banco de dados de benefício de usar. Na verdade, a configuração inteira (host, porta, senha e assim por diante) deve ser armazenada em um arquivo de configuração e recuperada através da classe ConfigurationManager.

Atingindo o check-out para tocar algum código

Periodicamente, os administradores desejarão olhar a instância em execução para obter informações de diagnóstico sobre o servidor em execução. MongoDB suporta uma interface HTTP para interagir com ele, que executam o em uma porta numericamente 1000 maior do que a porta que está configurado para usar para comunicação de cliente normais. Dessa forma, como porta padrão MongoDB 27017, a interface HTTP pode ser encontrada na porta 28017, conforme mostrado no do Figura 4.

Figure 4 The HTTP Interface for Interacting with MongoDB

Figura 4 da Interface de HTTP para interagir com MongoDB

Essa interface HTTP também permite que uma abordagem mais de comunicação do estilo do REST, como contrário para o driver nativo no MongoDB.Driver e MongoDB.Linq; o site MongoDB possui os detalhes completos, mas essencialmente a URL de HTTP para acessar o conteúdo de uma coleção é dado por adicionar o nome do banco de dados e o nome da coleção, separados por barras, como mostrado no do Figura 5.

Figure 5 The HTTP URL for Accessing a Collection’s Contents

Da URL de HTTP para acessar o conteúdo de uma coleção, a Figura 5

Para obter mais detalhes sobre a criação de um cliente REST usando o WCF, consulte o artigo do MSDN “ do REST no Windows Communication Foundation (WCF) ”.

Um Yoda do Word

MongoDB é um produto de rápida evolução e esses artigos ao mesmo tempo, explorando as principais partes da funcionalidade do MongoDB, ainda deixar as áreas principais unexamined. Embora MongoDB não seja um substituto direto para o SQL Server, é comprovar a uma alternativa viável do armazenamento para as áreas onde o RDBMS tradicional não passagens tão bem. Da mesma forma, assim como MongoDB é uma evolução em andamento, portanto, é o projeto csharp mongodb.  No momento da redação deste artigo, muitos aprimoramentos novos fosse na versão beta, incluindo aperfeiçoamentos para trabalhar com coleções com rigidez de tipos usando objetos simples, bem como melhoraram muito suporte a LINQ. Mantenha um olho aberto em ambos.

Enquanto isso, no entanto, é hora de encerramento de som wave para MongoDB e ativar a nossa atenção a outras partes do mundo de um desenvolvedor que o programador de trabalho pode não estar familiarizado com (e deve ser, indiscutivelmente,). Por enquanto, porém, feliz de codificação e lembre-se de como o excelente Yoda mestre DevGuy disse, “ um DevGuy usa o código-fonte para o conhecimento e a defesa; nunca para uma invasão. ”

Ted Neward é uma entidade de segurança com Neward & Associates, uma empresa independente especializado em corporativa do Microsoft .NET Framework e Java plataforma de sistemas. Ele escreveu mais de 100 artigos, é um MVP de c#, palestrante da INETA e autor e co-autor de diversos livros, incluindo “ Professional F # 2. 0 ” (Wrox 2010). Ele consulta e mentors regularmente. Entrar em ted@tedneward.com de e leia seu blog em blogs.tedneward.comde .

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Sam Corder and Craig Wilson