Usar tablas elásticas mediante código
Este artículo describe cómo realizar operaciones de datos en tablas elásticas usando código.
Trabajar con el token de sesión
Como se menciona en Nivel de consistencia, puede lograr la consistencia a nivel de sesión pasando el token de sesión actual con sus solicitudes. Si no incluye el token de sesión, es posible que los datos que recupere no incluyan los cambios de datos que acaba de realizar.
Obtener el token de sesión
El token de sesión está disponible en la respuesta de todas las operaciones de escritura. Busque el valor x-ms-session-token
.
Para cualquier OrganizationResponse que realiza una operación de escritura, puede capturar el valor x-ms-session-token
en la colección Resultados.
Nota
DeleteResponse no devuelve actualmente el valor x-ms-session-token
. Más información: Problemas conocidos: valor de x-ms-session-token no devuelto para operaciones de eliminación.
string sessionToken = response.Results["x-ms-session-token"].ToString();
Enviar el token de sesión
La forma en que envía el token de sesión en una operación de lectura depende de si está utilizando el SDK o la API web.
Al realizar una operación que recupera datos, establezca el parámetro opcional SessionToken
en OrganizationRequest.
var request = new RetrieveRequest
{
Target = new EntityReference("contoso_sensordata", sensordataid),
ColumnSet = new ColumnSet("contoso_value"),
["partitionId"] = deviceId,
["SessionToken"] = sessionToken
};
Especificar PartitionId
Como se mencionó en Particionamiento y escalamiento horizontal, cada tabla elástica tiene una columna partitionid
que debe usar si elige aplicar una estrategia de particionamiento para la tabla. De lo contrario, no establezca un valor para la columna partitionid
.
Importante
Si elige utilizar una estrategia de partición para su tabla elástica, todas las operaciones en esa tabla o las referencias a registros en esa tabla DEBE especifica el valor de columna partitionid
para identificar de forma única el registro. No se genera ningún error si partitionid
no se especifica en el valor de búsqueda de la tabla de referencia, pero la búsqueda no podrá ubicar el registro cuando lo use. Debe documentar y hacer cumplir este requisito mediante revisiones de código para garantizar que sus datos sean coherentes y partitionid
se utilicen de forma adecuada para todas las operaciones.
Tras especificar un valor no nulo en la columna partitionid
al crear una fila, debe especificarlo al realizar cualquier otra operación de datos en la fila. No puede cambiar este valor más adelante.
Si no configura un valor partitionid
para un registro cuando se crea, el valor de la columna partitionid
permanece nulo y no puede cambiarlo más tarde. En este caso, puede identificar registros utilizando la clave principal como lo hace con las tablas estándar. No es necesario especificar un valor partitionid
.
Nota
En los ejemplos de este artículo se supone que está especificando un valor no nulo en la columna partitionid
.
Puede configurar el valor partitionid
de las siguientes maneras al realizar varias operaciones de datos.
Uso de la clave alternativa
Como se mencionó en Claves alternativas, cada tabla elástica tiene una clave alternativa llamada KeyForNoSqlEntityWithPKPartitionId
. Este clave alternativa combina la clave principal de la tabla con la columna partitionid
.
Si está utilizando una estrategia de partición, debe especificar un clave alternativa para especificar el valor partitionid
cuando usa operaciones Retrieve
, Update
o Delete
, o cuando configura una columna de búsqueda para otra tabla que hace referencia a un registro de tabla elástica.
Este ejemplo muestra cómo puede usar clave alternativa para especificar el valor partitionid
al usar solicitudes Retrieve
, Update
y Delete
en tablas elásticas.
var keys = new KeyAttributeCollection() {
{ "contoso_sensordataid", sensordataid },
{ "partitionid", deviceId }
};
var entity = new Entity("contoso_sensordata", keys)
Uso del parámetro partitionId
Actualmente, puede usar un parámetro partitionId
para especificar el valor de la columna partitionid
solo para las operaciones Retrieve
y Delete
. Más información: Problema conocido: el parámetro opcional partitionId no está disponible para todos los mensajes
Nota
El parámetro partitionId
no funciona con mensajes Create
, Update
o Upsert
y se ignora si se envía.
request["partitionId"] = "device-001"
Usando la columna de ID de partición directamente
Para las operaciones Create
, Upsert
o Update
, puede especificar directamente el valor de la columna partitionid
.
Este ejemplo muestra cómo puede especificar directamente el valor de la columna partitionid
en Entity
al ejecutar una operación Create
, Upsert
o Update
.
var entity = new Entity("contoso_sensordata", sensordataid)
{
Attributes = {
{ "partitionid", "device-001" }
}
};
Crear un registro en una tabla elástica
Este ejemplo crea una nueva fila en la tabla contoso_SensorData
con partitionid
establecido en deviceid
. También establece una columna ttlinseconds
que garantiza que la fila caduque después de un día (86 400 segundos) y se elimine de Dataverse automáticamente.
Este ejemplo también captura el valor de x-ms-session-token
que puede usar al recuperar el registro creado.
/// <summary>
/// Demonstrates creating a record with a partitionid and capturing the session token
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="deviceId">The value used as partitionid for the contoso_sensordata table. </param>
/// <param name="sessionToken">The current session token</param>
/// <returns>The Id of the created record.</returns>
public static Guid CreateExample(
IOrganizationService service,
string deviceId,
ref string sessionToken )
{
var entity = new Entity("contoso_sensordata")
{
Attributes =
{
{ "contoso_deviceid", deviceId },
{ "contoso_sensortype", "Humidity" },
{ "contoso_value", 40 },
{ "contoso_timestamp", DateTime.UtcNow},
{ "partitionid", deviceId },
{ "ttlinseconds", 86400 } // 86400 seconds in a day
}
};
var request = new CreateRequest {
Target = entity
};
var response = (CreateResponse)service.Execute(request);
// Capture the session token
sessionToken = response.Results["x-ms-session-token"].ToString();
return response.id;
}
Utilice el valor x-ms-session-token
devuelto para establecer el parámetro opcional SessionToken
al recuperar el registro que creó. Obtenga más información sobre cómo enviar el token de sesión.
Nota
La inserción profunda no está admitida con tablas elásticas. Cada registro relacionado debe crearse de forma independiente. Sólo las mesas estándar admiten insertos profundos
Establecer el valor de la clave principal
Si no especifica un valor de clave principal, Dataverse establece un valor de clave principal para el registro cuando lo crea. Dejar a Dataverse establecer este valor es la práctica normal. Puede especificar el valor de la clave principal si es necesario. Para las tablas elásticas, no hay ningún beneficio en el rendimiento al permitir Dataverse que establezca el valor de la clave principal.
Las tablas elásticas no devuelven un error cuando crea un registro con un valor de clave principal que no es único. Al establecer los valores de clave principal con tablas elásticas, puede crear registros que tengan los mismos valores de clave principal y diferentes valores partitionid
. Sin embargo, este patrón no es compatible con Power Apps. No cree registros con valores de clave principal duplicados cuando las personas necesiten usar estos datos en lienzos o aplicaciones basadas en modelos.
Actualizar un registro en una tabla elástica
Este ejemplo actualiza los valores contoso_value
y contoso_timestamp
de una fila existente en la tabla contoso_SensorData
usando la clave principal contoso_sensordataid
y partitionid
= 'device-001'
.
Si usa una estrategia de partición, la clave principal y las columnas partitionid
son necesarias para identificar de forma única una fila de tabla elástica existente. El valor partitionid
de una fila existente no se puede actualizar y solo se usa para identificar de forma única la fila que se va a actualizar.
Este ejemplo usa la clave KeyForNoSqlEntityWithPKPartitionId
alternativa para identificar de manera única el registro usando tanto la clave principal como valores partitionid
. Más información sobre claves alternativas.
Este ejemplo muestra el uso del valor partitionid
como clave alternativa.
/// <summary>
/// Demonstrates updating elastic table row with partitionid as alternate key.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="sensordataid">The unique identifier of the contoso_sensordata table.</param>
/// <param name="deviceId">The value used as partitionid for the contoso_sensordata table. </param>
/// <param name="sessionToken">The current session token</param>
public static void UpdateExample(
IOrganizationService service,
Guid sensordataid,
string deviceId,
ref string sessionToken)
{
var keys = new KeyAttributeCollection() {
{ "contoso_sensordataid", sensordataid },
{ "partitionid", deviceId }
};
var entity = new Entity("contoso_sensordata", keys)
{
Attributes = {
{ "contoso_value", 60 },
{ "contoso_timestamp", DateTime.UtcNow }
}
};
var request = new UpdateRequest {
Target = entity,
["SessionToken"] = sessionToken
};
var response = (UpdateResponse)service.Execute(request);
// Capture the session token
sessionToken = response.Results["x-ms-session-token"].ToString();
}
Obtenga más información sobre el uso de la clase Entity para establecer claves alternativas.
Recuperar un registro en una tabla elástica
Si el valor partitionid
se estableció cuando creó un registro de tabla elástica, debe usarlo junto con el valor de la clave principal para identificar un registro de manera única.
Si no se configuró partitionid
, puede recuperar el registro normalmente usando solo el valor de la clave principal.
Hay dos formas diferentes de redactar una solicitud para recuperar un registro usando el valor partitionid
.
Este ejemplo usa la clase RetrieveRequest. La propiedad Target
está establecida en una EntityReference creada usando el constructor que acepta KeyAttributeCollection para usar la clave alternativa KeyForNoSqlEntityWithPKPartitionId
. Obtenga más información sobre el uso de la clase EntityReference con claves alternativas.
public static void RetrieveExampleAlternateKey(IOrganizationService service, Guid sensorDataId, string deviceId) {
var keys = new KeyAttributeCollection() {
{ "contoso_sensordataid", sensorDataId },
{ "partitionid", deviceId }
};
var entityReference = new EntityReference("contoso_sensordata", keys);
var request = new RetrieveRequest {
ColumnSet = new ColumnSet("contoso_value"),
Target = entityReference
};
var response = (RetrieveResponse)service.Execute(request);
Console.WriteLine($"contoso_value: {response.Entity.GetAttributeValue<int>("contoso_value")}");
}
Este ejemplo usa un parámetro opcional llamado partitionId
en la clase RetrieveRequest. Más información sobre el uso de parámetros opcionales.
public static void RetrieveExampleOptionalParameter(IOrganizationService service, Guid sensorDataId, string deviceId)
{
var entityReference = new EntityReference("contoso_sensordata", sensorDataId);
var request = new RetrieveRequest
{
ColumnSet = new ColumnSet("contoso_value"),
Target = entityReference,
["partitionId"] = deviceId
};
var response = (RetrieveResponse)service.Execute(request);
Console.WriteLine($"contoso_value: {response.Entity.GetAttributeValue<int>("contoso_value")}");
}
Filas de consulta de una tabla elástica
Cuando consulta las filas de una tabla elástica, obtiene el mejor rendimiento si limita su consulta a una partición específica. De lo contrario, su consulta devuelve datos en todas las particiones lógicas, lo que no es tan rápido.
Nota
Cuando usa este enfoque, el parámetro debe usar el nombre partitionId
(con mayúscula I) en lugar de partitionid
(todas en minúsculas).
Cuando especifica un filtro de esta manera, no tiene que especificar los criterios de filtro en partitionid
en su consulta de la manera habitual (es decir, usando FetchXML condition
, QueryExpression ConditionExpression o API web $filter
).
Especificar un filtro en el valor partitionid
de la manera habitual no tiene los mismos beneficios de rendimiento que especificarlo a través del parámetro partitionId
como se muestra en los siguientes ejemplos.
Estos ejemplos recuperan las primeras 5000 filas en la tabla contoso_SensorData
que pertenecen a partición lógica en la que partitionid
= 'deviceid-001'
.
public static EntityCollection RetrieveMultipleExample(IOrganizationService service)
{
var request = new RetrieveMultipleRequest
{
Query = new QueryExpression("contoso_sensordata")
{
ColumnSet = new ColumnSet("contoso_value")
},
["partitionId"] = "deviceid-001"
};
var response = (RetrieveMultipleResponse)service.Execute(request);
return response.EntityCollection;
}
Devolver filas relacionadas en una consulta
Actualmente, las tablas elásticas no admiten la devolución de filas relacionadas al ejecutar una consulta. Si intenta devolver filas relacionadas, Dataverse emite un error con el código 0x80048d0b
y el siguiente mensaje:
Link entities are not supported
.
Sin embargo, las tablas elásticas admiten la devolución de filas relacionadas al recuperar una sola fila.
Upsert en un registro en una tabla elástica
Importante
Las operaciones de upsert con tablas elásticas son diferentes a las operaciones upsert con tablas estándar. Se espera que las operaciones Upsert contengan la carga útil completa y sobrescribirán cualquier dato de registro existente. No llaman a los mensajes Create
o Update
. Obtenga más información sobre la elevación de la tabla elástica.
Con tablas elásticas, si un registro tiene una ID dada y partitionid
no existe, se creará. Si ya existe, se reemplaza.
Este ejemplo altera una fila en la tabla contoso_SensorData
con los id
y el valor partitionid
= deviceid-001
especificados.
/// <summary>
/// Demonstrates an upsert operation
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="id">The id of the record to update or create.</param>
/// <param name="sessionToken">The current session token</param>
/// <returns>Whether a record was created or not</returns>
public static bool UpsertExample(IOrganizationService service, Guid id, ref string sessionToken)
{
var entity = new Entity("contoso_sensordata", id)
{
Attributes = {
{ "contoso_deviceid", "deviceid-001" },
{ "contoso_sensortype", "Humidity" },
{ "contoso_value", 60 },
{ "contoso_timestamp", DateTime.UtcNow },
{ "partitionid", "deviceid-001" },
{ "ttlinseconds", 86400 }
}
};
var request = new UpsertRequest
{
Target = entity,
["SessionToken"] = sessionToken
};
var response = (UpsertResponse)service.Execute(request);
// Capture the session token
sessionToken = response.Results["x-ms-session-token"].ToString();
return response.RecordCreated;
}
Eliminar un registro en una tabla elástica
Al eliminar un registro que utiliza un valor personalizado partitionid
, debe incluir el valor partitionid
.
Este ejemplo elimina una fila en la tabla contoso_SensorData
con ID = y partitionid
= 'deviceid-001'
especificado.
/// <summary>
/// Demonstrates a delete operation
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="sensordataid">The unique identifier of the contoso_sensordata table.</param>
/// <param name="sessionToken">The current session token</param>
public static void DeleteExample(
IOrganizationService service,
Guid sensordataid,
ref string sessionToken)
{
var request = new DeleteRequest
{
Target = new EntityReference("contoso_sensordata", sensordataid),
["partitionId"] = "deviceid-001"
};
var response = service.Execute(request);
// Known issue: Value not currently being returned.
// sessionToken = response.Results["x-ms-session-token"].ToString();
}
Asociar registros de tabla elástica
Cuando un registro de tabla hace referencia a un registro de tabla elástica donde el valor de la columna partitionid
es nulo, puede asociar un registro en esa tabla a un registro de tabla elástica tal como los registros estándar. Consulte SDK para .NET, o la API web.
Cuando un registro de tabla hace referencia a un registro de tabla elástica que tiene un valor de columna partitionid
establecido, debe incluir el valor de columna partitionid
del registro de tabla elástica cuando configura la columna de búsqueda de la tabla de referencia. Puede hacer esto incluyendo el valor como clave alternativa.
Como se describe en Columna de valor de ID de partición en la tabla de referencia, cuando se crea una relación de uno a muchos y la tabla elástica es la tabla referencia, una columna de cadena y una columna de búsqueda se crean en la tabla referenciada. La columna cadena almacena el valor partitionid
del registro de la tabla elástica referenciada.
Puede configurar los valores de la columna de búsqueda y de cadena con sus respectivos valores de la siguiente manera:
- Usando una referencia de clave alternativa para configurar solo la búsqueda
- Establecer los valores de dos columnas juntos en una actualización
La forma de hacer esto depende de si está utilizando SDK para .NET o Web API
Este ejemplo asocia un registro de tabla elástica contoso_SensorData
con el identificador especificado y partitionid
a un registro de cuenta existente configurando la columna de búsqueda con un clave alternativa:
/// <summary>
/// Demonstrates associate to elastic table operation.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="sensordataId">The unique identifier of the contoso_sensordata table.</param>
/// <param name="deviceId">The deviceId. PartitionId of sensor data record.</param>
/// <param name="accountId">The unique identifier of the account record to update.</param>
public static void AssociateAccountAlternateKeyExample(
IOrganizationService service,
Guid sensordataId,
string deviceId,
Guid accountId)
{
var keys = new KeyAttributeCollection() {
{ "contoso_sensordataid", sensordataId },
{ "partitionid", deviceId }
};
var sensorDataReference = new EntityReference("contoso_sensordata", keys);
Entity account = new("account", accountId)
{
Attributes =
{
{"contoso_sensordata", sensorDataReference}
}
};
service.Update(account);
}
Este ejemplo hace lo mismo, pero junta ambas columnas:
/// <summary>
/// Demonstrates associate to elastic table operation.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="sensordataId">The unique identifier of the contoso_sensordata table.</param>
/// <param name="deviceId">The deviceId. PartitionId of sensor data record.</param>
/// <param name="deviceId">The unique identifier of the account record to update.</param>
public static void AssociateAccountBothColumnsExample(
IOrganizationService service,
Guid sensordataId,
string deviceId,
Guid accountId)
{
Entity account = new("account", accountId) {
Attributes =
{
{"contoso_sensordata", new EntityReference("contoso_sensordata", sensordataId)},
{"contoso_sensordatapid", deviceId }
}
};
service.Update(account);
}
Finalmente, este ejemplo muestra el uso de AssociateRequest para asociar una colección de registros account
al mismo registro de tabla contoso_SensorData
en una sola operación.
/// <summary>
/// Demonstrates associating multiple accounts to a contoso_sensordata elastic table record
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="sensordataId">The unique identifier of the contoso_sensordata table.</param>
/// <param name="deviceId">The deviceId. PartitionId of sensor data record.</param>
/// <param name="relatedEntities">A collection of references to account records to associate to the contoso_sensordata elastic table record</param>
public static void AssociateMultipleElasticTableExample(
IOrganizationService service,
Guid sensordataId,
string deviceId,
EntityReferenceCollection relatedEntities)
{
// The keys to the elastic table record including the partitionid
var keys = new KeyAttributeCollection() {
{ "contoso_sensordataid", sensordataId },
{ "partitionid", deviceId }
};
AssociateRequest request = new()
{
Target = new EntityReference("contoso_sensordata", keys),
Relationship = new Relationship("contoso_SensorData_contoso_SensorData_Acc"),
RelatedEntities = relatedEntities
};
service.Execute(request);
}
Operaciones masivas con tablas elásticas
A menudo, las aplicaciones deben ingerir una gran cantidad de datos en Dataverse en poco tiempo. Dataverse tiene un grupo de mensajes que están diseñados para lograr un alto rendimiento. Con mesas elásticas, el rendimiento puede ser incluso mayor.
Las operaciones masivas están optimizadas para el rendimiento cuando se realizan varias operaciones de escritura en la misma tabla tomando un lote de filas como entrada en una sola operación de escritura. Más información sobre los mensajes de operaciones masivas (vista previa).
Use CreateMultiple con tablas elásticas
Puede usar el mensaje CreateMultiple
con el SDK para .NET o la API web.
Este ejemplo usa la clase CreateMultipleRequest para crear varias filas en la tabla elástica contoso_SensorData
.
public static Guid CreateMultiple(IOrganizationService service)
{
string tableLogicalName = "contoso_sensordata";
List<Microsoft.Xrm.Sdk.Entity> entityList = new List<Microsoft.Xrm.Sdk.Entity>
{
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_deviceId", "deviceid-001" },
{ "contoso_sensortype", "Humidity" },
{ "contoso_value", "40" },
{ "contoso_timestamp", "2023-05-01Z05:00:00"},
{ "partitionid", "deviceid-001" },
{ "ttlinseconds", 86400 }
}
},
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_deviceId", "deviceid-002" },
{ "contoso_sensortype", "Humidity" },
{ "contoso_value", "10" },
{ "contoso_timestamp", "2023-05-01Z09:30:00"},
{ "partitionid", "deviceid-002" },
{ "ttlinseconds", 86400 }
}
}
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_deviceId", "deviceid-002" },
{ "contoso_sensortype", "Pressure" },
{ "contoso_value", "20" },
{ "contoso_timestamp", "2023-05-01Z07:20:00"},
{ "partitionid", "deviceid-002" },
{ "ttlinseconds", 86400 }
}
}
};
// Create an EntityCollection populated with the list of entities.
EntityCollection entities = new(entityList)
{
EntityName = tableLogicalName
};
// Use CreateMultipleRequest
CreateMultipleRequest createMultipleRequest = new()
{
Targets = entities,
};
return service.Execute(request);
}
Use UpdateMultiple con tablas elásticas
Puede usar el mensaje UpdateMultiple
con el SDK para .NET o la API web.
Este ejemplo usa la clase UpdateMultipleRequest para actualizar varias filas en la tabla elástica contoso_SensorData
. Estas actualizaciones establecen la columna contoso_value
.
public static Guid UpdateMultiple(IOrganizationService service)
{
string tableLogicalName = "contoso_sensordata";
List<Microsoft.Xrm.Sdk.Entity> entityList = new List<Microsoft.Xrm.Sdk.Entity>
{
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_value", "45" },
{ "partitionid", "deviceid-001" }
}
},
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_value", "15" },
{ "partitionid", "deviceid-002" }
}
}
new Microsoft.Xrm.Sdk.Entity(tableLogicalName)
{
Attributes =
{
{ "contoso_value", "25" },
{ "partitionid", "deviceid-002" }
}
}
};
// Create an EntityCollection populated with the list of entities.
EntityCollection entities = new(entityList)
{
EntityName = tableLogicalName
};
// Use UpdateMultipleRequest
UpdateMultipleRequest updateMultipleRequest = new()
{
Targets = entities,
};
return service.Execute(request);
}
Use DeleteMultiple con tablas elásticas
Puede usar el mensaje DeleteMultiple
con el SDK para .NET o la API web.
Nota
Con el SDK, debe usar la clase OrganizationRequest porque el SDK actualmente no tiene una clase DeleteMultipleRequest
. Más información sobre usar mensajes con SDK para .NET.
El siguiente método estático DeleteMultipleExample
utiliza el mensaje DeleteMultiple
con la clase OrganizationRequest para eliminar varias filas de la tabla elástica contoso_SensorData
. La clave alternativa se usa para incluir el valor partitionid
para identificar de forma única las filas.
public static void DeleteMultipleExample(IOrganizationService service)
{
string tableLogicalName = "contoso_sensordata";
List<EntityReference> entityReferences = new() {
{
new EntityReference(logicalName: tableLogicalName,
keyAttributeCollection: new KeyAttributeCollection
{
{ "contoso_sensordataid", "3f56361a-b210-4a74-8708-3c664038fa41" },
{ "partitionid", "deviceid-001" }
})
},
{ new EntityReference(logicalName: tableLogicalName,
keyAttributeCollection: new KeyAttributeCollection
{
{ "contoso_sensordataid", "e682715b-1bba-415e-b2bc-de9327308423" },
{ "partitionid", "deviceid-002" }
})
}
};
OrganizationRequest request = new(requestName:"DeleteMultiple")
{
Parameters = {
{"Targets", new EntityReferenceCollection(entityReferences)}
}
};
service.Execute(request);
}
Pasos siguientes
Aprenda a usar código para crear y consultar datos de notación de objetos JavaScript (JSON) en columnas JSON en tablas elásticas con código.
Consulte también
Tablas elásticas para desarrolladores
Crear tablas elásticas mediante código
Consultar columnas JSON en tablas elásticas
Código de ejemplo de tablas elásticas
Mensajes de operación masiva (versión preliminar)