TigerZF
🌐Español

Capítulo 19. API SimpleCloud: Zend_Cloud

Tabla de contenidos

19.1. Introducción al Document Service
19.1.1. Interfaz Zend_Cloud_DocumentService_Adapter
19.1.2. Opciones de adaptador soportadas
19.1.3. Conceptos básicos
19.1.4. Excepciones
19.1.5. Crear una colección
19.1.6. Eliminar una colección
19.1.7. Listar las colecciones disponibles
19.1.8. Insertar un documento
19.1.9. Reemplazar un documento
19.1.10. Actualizar un documento
19.1.11. Eliminar un documento
19.1.12. Obtener un documento
19.1.13. Consultar una colección
19.1.14. Crear una consulta
19.1.15. Acceder a los adaptadores concretos
19.2. Introducción al Queue Service
19.2.1. Instanciar y configurar los adaptadores de QueueService
19.2.1.1. Opciones específicas del servicio
19.2.2. Conceptos básicos
19.2.3. Excepciones
19.2.4. Crear una cola
19.2.5. Eliminar una cola
19.2.6. Listar colas
19.2.7. Establecer los metadatos de una cola
19.2.8. Obtener los metadatos de una cola
19.2.9. Enviar un mensaje
19.2.10. Recibir un mensaje
19.2.11. Eliminar un mensaje
19.2.12. Acceder a los adaptadores concretos
19.3. Introducción al StorageService
19.3.1. Adaptadores de StorageService
19.3.1.1. Opciones del adaptador de StorageService
19.3.2. Conceptos básicos
19.3.3. Excepciones
19.3.4. Almacenar un elemento
19.3.5. Obtener un elemento
19.3.6. Eliminar un elemento
19.3.7. Copiar un elemento
19.3.8. Mover un elemento
19.3.9. Renombrar un elemento
19.3.10. Listar elementos
19.3.11. Obtener metadatos
19.3.12. Almacenar metadatos
19.3.13. Eliminar metadatos
19.3.14. Acceder a los adaptadores concretos
19.4. Zend_Cloud_Infrastructure
19.4.1. Resumen
19.4.2. Inicio rápido
19.4.3. Métodos disponibles
19.4.4. Ejemplos
19.5. Zend_Cloud_Infrastructure_Adapter
19.5.1. Adaptadores
19.5.2. AMAZON EC2
19.5.3. Rackspace Cloud Servers

19.1. Introducción al Document Service

Zend_Cloud_DocumentService abstrae las interfaces de todas las principales bases de datos de documentos - tanto en la nube como desplegadas localmente - de modo que los desarrolladores puedan acceder a su funcionalidad común a través de una única API. En otras palabras, una aplicación puede hacer uso de estas bases de datos y servicios sin preocuparse de cómo se desplegará la aplicación. El origen de datos puede elegirse únicamente mediante cambios de configuración en el momento del despliegue.

Las bases de datos y servicios de documentos son cada vez más comunes en el desarrollo de aplicaciones. Estos orígenes de datos son algo diferentes de los orígenes de datos relacionales tradicionales, ya que evitan las relaciones complejas en favor del rendimiento, la escalabilidad y la flexibilidad. Ejemplos de servicios orientados a documentos incluyen Amazon SimpleDB y Azure Table Storage.

La API SimpleCloud ofrece cierta flexibilidad para características específicas del proveedor mediante un array $options en la firma de cada método. Algunos adaptadores requieren ciertas opciones que también deben añadirse al array $options. Es una buena práctica obtener estas opciones de un archivo de configuración para mantener la compatibilidad con todos los servicios y bases de datos; las opciones no reconocidas simplemente se descartarán, lo que permite usar diferentes servicios según el entorno.

Si se requieren más requisitos específicos del proveedor, el desarrollador debe extender el adaptador específico de Zend_Cloud_DocumentService para añadir soporte para dichas características. De este modo, las características específicas del proveedor pueden invocarse en la aplicación haciendo referencia a las extensiones de la API SimpleCloud en la subclase del adaptador Simple Cloud.

19.1.1. Interfaz Zend_Cloud_DocumentService_Adapter

La interfaz Zend_Cloud_DocumentService_Adapter define los métodos que implementa cada adaptador concreto de servicio de documentos. Los siguientes adaptadores se distribuyen con la API SimpleCloud:

Para instanciar un adaptador de servicio de documentos, utilice el método estático Zend_Cloud_DocumentService_Factory::getAdapter(), que acepta un array de configuración o un objeto Zend_Config. La clave document_adapter debe especificar el nombre de la clase del adaptador concreto. También pueden pasarse en este parámetro de configuración claves específicas del adaptador.

Ejemplo 19.1. Ejemplo: Uso del adaptador SimpleDB

$adapterClass = 'Zend_Cloud_DocumentService_Adapter_SimpleDb';
$documents = Zend_Cloud_DocumentService_Factory::getAdapter(array(
    Zend_Cloud_DocumentService_Factory::DOCUMENT_ADAPTER_KEY    => $adapterClass,
    Zend_Cloud_DocumentService_Adapter_SimpleDb::AWS_ACCESS_KEY => $amazonKey,
    Zend_Cloud_DocumentService_Adapter_SimpleDb::AWS_SECRET_KEY => $amazonSecret
));

19.1.2. Opciones de adaptador soportadas

Tabla 19.1. Opciones comunes de Zend_Cloud_DocumentService_Adapter

Clave de opción Descripción Utilizada en Requerida Por defecto
document_class

Clase a usar para representar los documentos devueltos. La clase proporcionada debe extender Zend_Cloud_DocumentService_Document para garantizar la compatibilidad con todos los servicios de documentos. Para todos los métodos que devuelven un documento o una colección de documentos, se utilizará esta clase.

Constructor No Zend_Cloud_Document_Service_Document
documentset_class

Clase a usar para representar colecciones de documentos, Zend_Cloud_DocumentService_DocumentSet por defecto. Normalmente, objetos de esta clase serán devueltos por listDocuments() y query(). Cualquier clase proporcionada para este valor de configuración debe extender Zend_Cloud_DocumentService_DocumentSet.

Constructor No Zend_Cloud_DocumentService_DocumentSet

Tabla 19.2. Opciones de Zend_Cloud_DocumentService_Adapter_SimpleDb

Clave de opción Descripción Utilizada en Requerida Por defecto
query_class

Clase a usar para crear y ensamblar consultas para este servicio de documentos; select() creará objetos de este nombre de clase, al igual que listDocuments().

Constructor No Zend_Cloud_DocumentService_Adapter_SimpleDb_Query
aws_accesskey Su clave de acceso de Amazon AWS Constructor Ninguno
aws_secretkey Su clave secreta de Amazon AWS Constructor Ninguno
http_adapter Adaptador HTTP a usar en todas las operaciones de acceso Constructor No Zend_Http_Client_Adapter_Socket
merge

Si es un booleano true, todos los valores de atributos se fusionan. También puede especificar un array de pares clave, donde la clave es la clave del atributo a fusionar, y el valor indica si se debe fusionar o no; un valor booleano true fusionará la clave dada. Cualquier atributo no especificado en este array será reemplazado.

updateDocument() No True
return_documents

Si es un booleano true, query() devuelve un objeto Zend_Cloud_DocumentService_DocumentSet que contiene objetos Zend_Cloud_DocumentService_Document (caso por defecto); en caso contrario, devuelve un array de arrays.

query() No True

Tabla 19.3. Opciones de Zend_Cloud_DocumentService_Adapter_WindowsAzure

Clave de opción Descripción Utilizada en Requerida Por defecto
query_class

Clase a usar para crear y ensamblar consultas para este servicio de documentos; select() creará objetos de este nombre de clase, al igual que listDocuments().

Constructor No Zend_Cloud_DocumentService_Adapter_WindowsAzure_Query
default_partition_key

La clave de partición por defecto a usar si no se especifica ninguna en el identificador del documento. Windows Azure requiere un identificador de documento de dos partes, formado por una PartitionKey y una RowKey. La PartitionKey normalmente será común para los documentos de una única colección - y potencialmente incluso en toda su instancia de tabla. Como tal, este ajuste le permite especificar la PartitionKey por defecto a utilizar para todos los documentos.

Si no se especifica, el adaptador utilizará por defecto el nombre de la colección como PartitionKey.

Constructor, setDefaultPartitionKey() Nombre de la colección a la que pertenece el documento
storage_accountname Nombre de cuenta de Windows Azure Constructor Ninguno
storage_accountkey Clave de cuenta de Windows Azure Constructor Ninguno
storage_host

Host de acceso de Windows Azure, el valor por defecto es table.core.windows.net

Constructor No table.core.windows.net
storage_proxy_host Nombre de host del proxy Constructor No Ninguno
storage_proxy_port Puerto del proxy Constructor No 8080
storage_proxy_credentials Credenciales del proxy Constructor No Ninguno
HTTP Adapter Adaptador HTTP a usar en todas las operaciones de acceso Constructor No Ninguno
verify_etag

Verifica el ETag en el documento de destino y realiza la operación solo si el ETag coincide con el valor esperado

updateDocument(), replaceDocument(), deleteDocument() No False

19.1.3. Conceptos básicos

Cada servicio y base de datos orientados a documentos utiliza su propia terminología y construcciones en su API. La API SimpleCloud identifica y abstrae una serie de conceptos y operaciones comunes que se comparten entre los proveedores.

El almacenamiento de documentos consiste en varias colecciones, que son unidades de almacenamiento lógicas análogas a las tablas de bases de datos en el mundo SQL. Las colecciones contienen documentos, que son esencialmente un conjunto de pares clave-valor, junto con algunos metadatos específicos del motor de almacenamiento, y se identifican mediante un ID de documento único.

Cada documento tiene su propia estructura (conjunto de campos) que no necesariamente debe coincidir con la estructura de ningún otro documento, incluso dentro de la misma colección. De hecho, puede cambiar esta estructura después de que el documento haya sido creado.

Los documentos pueden recuperarse por ID o mediante una consulta a una colección.

Los documentos se representan mediante la clase Zend_Cloud_DocumentService_Document. Tenga en cuenta que la clase de documento no valida los ID y datos suministrados, y no impone la compatibilidad con los requisitos de cada adaptador.

Se puede acceder a los campos del documento usando las claves como propiedades de objeto y como elementos de array.

La interfaz básica de Zend_Cloud_DocumentService_Document es la siguiente:

/**
 * ArrayAccess allows accessing fields by array key:
 *    $doc['fieldname']
 *
 * IteratorAggregate allows iterating over all fields:
 *    foreach ($document as $field => $value) {
 *        echo "$field: $value\n";
 *    }
 *
 * Countable provides a count of all fields:
 *    count($document)
 */
class Zend_Cloud_DocumentService_Document
    implements ArrayAccess, IteratorAggregate, Countable
{
    const KEY_FIELD = '_id';

    /**
     * $fields may be an array or an object implementing ArrayAccess.
     * If no $id is provided, it will look for a field matching KEY_FIELD to
     * use as the identifier.
     */
    public function __construct($fields, $id = null);

    public function setId($id);
    public function getId();
    public function getFields();
    public function getField($name);
    public function setField($name, $value);

    /**
     * These allow overloading, so you may access fields as if they were
     * native properties of the document
     */
    public function __get($name);
    public function __set($name, $value);

    /**
     * Alternately, you can acces fields as if via native getters and
     * setters:
     *     $document->setFoo($value);    // set "Foo" field to value
     *     $value = $document->getFoo(); // get "Foo" field value
    public function __call($name, $args);
}
[Note] Identificadores de documentos en Windows Azure

Windows Azure técnicamente requiere una combinación de dos campos para identificar de forma única los documentos: la PartitionKey y la RowKey, y como tal, las claves están completamente calificadas por la estructura array(PartitionKey, RowKey) -- lo que las hace no portables. En la mayoría de las situaciones, la PartitionKey no diferirá para los documentos de una única colección -- y potencialmente ni siquiera en toda su instancia de tabla. Como tal, el DocumentService ofrece varias opciones para especificar claves:

  • Las claves de tipo array siempre funcionarán como se espera.

  • Si se proporciona una clave de tipo string:

    • Si se proporcionó el ajuste default_partition_key al constructor, o se pasó al método setDefaultPartitionKey(), ese valor se usará para la PartitionKey.

    • En caso contrario, se usará el nombre de la colección sobre la que está operando.

La conclusión es que puede utilizar claves de tipo string si desea maximizar la portabilidad de su aplicación. Solo tenga en cuenta que su registro contendrá unos pocos campos adicionales para denotar la clave (PartitionKey, RowKey, y el Timestamp del que no se había hablado antes) en caso de que alguna vez migre sus datos a otro servicio.

Ejemplo 19.2. Crear un documento

$document = new Zend_Cloud_DocumentService_Document(array(
    'key1' => 'value1',
    'key2' => 123,
    'key3' => 'thirdvalue',
), "DocumentId");
$document->otherkey = 'some more data';
echo "key 1: " . $document->key1   . "\n"; // object notation
echo "key 2: " . $document['key2'] . "\n"; // array notation

Ejemplo 19.3. Explorar los datos del documento

$document = $documents->fetchDocument("mydata", $id);
echo "Document ID: " . $document->getID() . "\n";
foreach ($document->getFields() as $key => $value) {
    echo "Field $key is $value\n";
}

19.1.4. Excepciones

Si ocurre algún error en el servicio de documentos, se lanza Zend_Cloud_DocumentService_Exception. Si la excepción fue causada por el controlador del servicio subyacente, puede usar el método getClientException() para recuperar la excepción original.

Dado que los diferentes proveedores en la nube implementan diferentes conjuntos de servicios, algunos controladores no implementan ciertas características. En este caso, se lanza la excepción Zend_Cloud_OperationNotAvailableException.

19.1.5. Crear una colección

Se crea una nueva colección usando createCollection().

Ejemplo 19.4. Crear una colección

$documents->createCollection("mydata");

Si llama a createCollection() con un nombre de colección que ya existe, el servicio no hará nada y dejará la colección existente sin modificar.

19.1.6. Eliminar una colección

Una colección se elimina llamando a deleteCollection().

Ejemplo 19.5. Eliminar una colección

$documents->deleteCollection("mydata");

Eliminar una colección elimina automáticamente todos los documentos contenidos en esa colección.

[Note] Nota

Eliminar una colección puede llevar un tiempo considerable en algunos servicios. No puede volver a crear una colección con el mismo nombre hasta que la colección y todos sus documentos se hayan eliminado por completo.

Eliminar una colección inexistente no tendrá ningún efecto.

19.1.7. Listar las colecciones disponibles

Una lista de las colecciones existentes se devuelve mediante listCollections(). Este método devuelve un array con todos los nombres de las colecciones pertenecientes a la cuenta que especificó al crear el adaptador.

Ejemplo 19.6. Listar colecciones

$list = $documents->listCollections();
foreach ($list as $collection) {
    echo "My collection: $collection\n";
}

19.1.8. Insertar un documento

Para insertar un documento, necesita proporcionar un objeto Zend_Cloud_DocumentService_Document o un array asociativo de datos, así como la colección en la que lo está insertando.

Muchos proveedores requieren que proporcione un ID de documento junto con su documento. Si usa un objeto Zend_Cloud_DocumentService_Document, puede especificarlo pasando el identificador al constructor al instanciar el objeto. Si usa un array asociativo, el nombre de la clave será específico del adaptador; por ejemplo, en Azure, el ID está compuesto por la PartitionKey y la RowKey; en Amazon SimpleDB, el ID es el ItemName; también puede especificar la clave en el campo _id para una mayor portabilidad.

Como tal, la forma más sencilla y compatible de especificar la clave es usar un objeto Document.

Ejemplo 19.7. Insertar un documento

// Instantiating and creating the document
$document = new Zend_Cloud_DocumentService_Document(array(
    'key1' => 'value1',
    'key2' => 123,
    'key3' => 'thirdvalue',
), "DocumentID");

// inserting into the "mydata" collection
$documents->insertDocument("mydata", $document);

19.1.9. Reemplazar un documento

Reemplazar un documento significa eliminar todos los datos del documento asociados a una clave de documento en particular y sustituirlos por un nuevo conjunto de datos. A diferencia de actualizar, esta operación no fusiona los datos antiguos y nuevos, sino que reemplaza el documento en su totalidad. La operación de reemplazo, al igual que insertDocument(), acepta un documento Zend_Cloud_DocumentService_Document o un array de pares clave-valor que especifican los nombres y valores de los nuevos campos, y la colección en la que existe el documento.

[Note] Se requiere el ID del documento

Para reemplazar el documento, se requiere el ID del documento. Al igual que al insertar un documento, si usa un array asociativo para describir el documento, necesitará proporcionar una clave específica del proveedor que indique el ID del documento. Como tal, la forma más compatible de reemplazar un documento entre proveedores es utilizar un objeto Document, como se muestra en los ejemplos.

Ejemplo 19.8. Reemplazar un documento

$document = new Zend_Cloud_DocumentService_Document(array(
    'key1' => 'value1',
    'key2' => 123,
    'key3' => 'thirdvalue',
), "DocumentID");

// Update the document as found in the "mydata" collection
$documents->replaceDocument("mydata", $document);

También puede usar un objeto Document existente, reasignar los campos y/o asignar nuevos campos, y pasarlo al método replaceDocument():

$docment->key4 = '4th value';

// Update the document as found in the "mydata" collection
$documents->replaceDocument("mydata", $document);

19.1.10. Actualizar un documento

Actualizar un documento cambia los pares clave/valor en un documento existente. Esta operación no comparte la semántica de reemplazo; los valores de las claves que no se especifican en el conjunto de datos no se cambiarán. Debe proporcionar tanto una clave de documento como datos, ya sea mediante un documento Zend_Cloud_DocumentService_Document o un array, a este método. Si la clave es null y se proporciona un objeto documento, se usa la clave del documento.

Ejemplo 19.9. Actualizar un documento

// update one field
$documents->updateDocument("mydata", "DocumentID", array("key2" => "new value"));

// or with document; this could be a document already retrieved from the service
$document = new Zend_Cloud_DocumentService_Document(array(
    'key1' => 'value1',
    'key2' => 123,
    'key3' => 'thirdvalue',
), "DocumentID");
$documents->updateDocument("mydata", null, $document);

// copy document to another ID
$documents->updateDocument("mydata", "AnotherDocumentID", $document);

Amazon SimpleDB admite campos multivaluados, por lo que las actualizaciones de datos se fusionarán con el valor de clave anterior en lugar de reemplazarlo. La opción merge debe contener un array de nombres de campos a fusionar. El array debe ser pares clave/valor, donde la clave corresponde a la clave del campo, y el valor un valor booleano que indica el estado de fusión (booleano true fusionaría; false no lo haría). Cualquier clave no especificada en la opción merge se reemplazará en lugar de fusionarse.

Ejemplo 19.10. Fusionar campos de documento

// key2 is overwritten, key3 is merged
$documents->updateDocument('mydata', 'DocumentID',
    array('key2' => 'new value', 'key3' => 'additional value'),
    array('merge' => array('key3' => true))
);

19.1.11. Eliminar un documento

Un documento puede eliminarse pasando su clave a deleteDocument(). Eliminar un documento inexistente no tiene ningún efecto.

Ejemplo 19.11. Eliminar un documento

$documents->deleteDocument("collectionName", "DocumentID");

19.1.12. Obtener un documento

Puede obtener un documento específico especificando su clave. fetchDocument() devuelve una instancia de Zend_Cloud_DocumentService_Document.

Ejemplo 19.12. Obtener un documento

$document = $service->fetchDocument('collectionName', 'DocumentID');
echo "Document ID: " . var_export($document->getID(), 1) . "\n";
foreach ($document->getFields() as $key => $value) {
    echo "Field $key is $value\n";
}

19.1.13. Consultar una colección

Para encontrar documentos en la colección que cumplan ciertos criterios, use el método query(). Este método acepta ya sea una cadena que es una consulta dependiente del adaptador y se pasa tal cual al adaptador concreto, o una instancia de un objeto de consulta estructurada de Zend_Cloud_DocumentService_Query. El valor de retorno es un Zend_Cloud_DocumentService_DocumentSet, que contiene instancias de Zend_Cloud_DocumentService_Document que satisfacen la consulta. El objeto DocumentSet es iterable y contable.

Ejemplo 19.13. Consultar una colección usando una consulta de cadena

$docs = $documents->query(
    "collectionName",
    "RowKey eq 'rowkey2' or RowKey eq 'rowkey2'"
);

foreach ($docs as $doc) {
    $id = $doc->getId();
    echo "Found document with ID: "
        . var_export($id, 1)
        . "\n";
}

Si usa un objeto de consulta estructurada, normalmente lo obtendrá mediante el método select(). Esto garantiza que el objeto de consulta sea específico de su adaptador, lo que asegura que se ensamble en una sintaxis que su adaptador entienda.

Ejemplo 19.14. Consultar una colección con una consulta estructurada

$query = $service->select();
$query->from('collectionName')
      ->where('year > ?', array(1945))
      ->limit(3);
$docs = $documents->query('collectionName', $query);

foreach ($docs as $doc) {
    $id = $doc->getId();
    echo "Found document with ID: "
        . var_export($id, 1)
        . "\n";
}

Las clases Zend_Cloud_DocumentService_Query no limitan qué cláusulas de consulta pueden usarse, pero la cláusula debe estar soportada por el adaptador concreto subyacente. Las cláusulas actualmente soportadas incluyen:

  • select() - define qué campos se devuelven en el resultado.

    [Note] Nota

    Windows Azure ignora el argumento de esta cláusula y siempre devuelve el documento completo.

  • from() - define el nombre de la colección usada en la consulta.

  • where() - define las condiciones de la consulta. Acepta tres parámetros: condición, array de argumentos para reemplazar los campos "?" en la condición, y un argumento de conjunción que debe ser "and" u "or", y que se usará para unir esta condición con condiciones anteriores. Pueden especificarse múltiples cláusulas where().

  • whereId() - define la condición por ID de documento (clave). El documento coincidente debe tener la misma clave. El método acepta un argumento - el ID (clave) requerido.

  • limit() - limita los datos devueltos al número especificado de documentos.

  • order() - ordena los datos devueltos por el campo especificado. Acepta dos argumentos - el primero es el nombre del campo y el segundo es 'asc' o 'desc' que especifica la dirección de ordenación.

    [Note] Nota

    Esta cláusula actualmente no está soportada por Windows Azure.

19.1.14. Crear una consulta

Para conveniencia del usuario, el método select() instancia un objeto de consulta específico del adaptador, y establece la cláusula SELECT para él.

Ejemplo 19.15. Crear una consulta estructurada

$query = $documents->select()
                   ->from('collectionName')
                   ->where('year > ?', array(1945))
                   ->limit(3);
$docs = $documents->query('collectionName', $query);
foreach ($docs as $doc) {
    $id = $doc->getId();
    echo "Found document with ID: "
        . var_export($id, 1)
        . "\n";
}

19.1.15. Acceder a los adaptadores concretos

En ocasiones es necesario recuperar el adaptador concreto para el servicio con el que está trabajando la API Document. Esto puede lograrse usando el método getAdapter().

[Note] Nota

Acceder al adaptador subyacente rompe la portabilidad entre servicios, por lo que debe reservarse solo para circunstancias excepcionales.

Ejemplo 19.16. Usar adaptadores concretos

// Since SimpleCloud Document API doesn't support batch upload, use concrete adapter
$amazonSdb = $documents->getAdapter();
$amazonSdb->batchPutAttributes($items, 'collectionName');