Consultar o banco de dados com queryDef query-database-api

Adobe Campaign fornece métodos avançados do JavaScript para interagir com o banco de dados usando queryDef e o objeto NLWS. Esses métodos baseados em SOAP permitem carregar, criar, atualizar e consultar dados usando JSON, XML ou SQL.

NOTE
Esta documentação abrange APIs orientadas por dados para consultar o banco de dados de forma programática. Para APIs REST, consulte Introdução às APIs REST. Para criação visual de consultas, consulte Trabalhar com o editor de consultas.

O que é NLWS? what-is-nlws

NLWS (Neolane Web Services) é o objeto global do JavaScript usado para acessar os métodos de API baseados em SOAP de Adobe Campaign. Os esquemas são propriedades do objeto NLWS, permitindo que você interaja com entidades do Campaign de forma programática.

De acordo com a documentação JSAPI do Campaign, "os esquemas são objetos globais 'NLWS'." A sintaxe para acessar métodos de esquema segue este padrão:

NLWS.<namespace><SchemaName>.<method>()

Exemplos:

  • NLWS.nmsRecipient - Métodos de acesso para o esquema do destinatário (nms:recipient)
  • NLWS.nmsDelivery - Métodos de acesso para o esquema de entrega (nms:delivery)
  • NLWS.xtkQueryDef - Acessar métodos queryDef para consultar o banco de dados

Os métodos comuns de API incluem:

  • load(id) - Carregar uma entidade pela respectiva ID. Saiba mais
  • create(data) - Criar uma nova entidade
  • save() - Salvar alterações em uma entidade

Exemplo da documentação oficial:

var delivery = NLWS.nmsDelivery.load("12435")
NOTE
Sintaxe alternativa: Para compatibilidade com versões anteriores, você também pode ver sintaxe de namespace em minúsculas em alguma documentação (por exemplo, nms.recipient.create(), xtk.queryDef.create()). Ambas as sintaxes funcionam, mas NLWS é o padrão documentado na referência oficial JSAPI do Campaign.

Pré-requisitos prerequisites

Antes de usar os métodos queryDef e NLWS, você deve se familiarizar com:

  • JavaScript
  • Esquemas e modelo de dados do Adobe Campaign
  • Expressões XPath para navegar por elementos de esquema

Noções básicas sobre o modelo de dados do Campaign:

O Adobe Campaign vem com um modelo de dados predefinido que consiste em tabelas vinculadas em um banco de dados na nuvem. A estrutura básica inclui:

  • Tabela de destinatários (nmsRecipient) - Tabela principal que armazena perfis de marketing

  • Tabela de entrega (nmsDelivery) - Armazena ações de entrega e modelos com parâmetros para executar entregas

  • Tabelas de logs - Logs de execução de armazenamento:

    • nmsBroadLogRcp - Logs de entrega para todas as mensagens enviadas aos destinatários
    • nmsTrackingLogRcp - Logs de rastreamento para reações do recipient (aberturas, cliques)
  • Tabelas técnicas - Armazene dados do sistema como operadores (xtkGroup), sessões (xtkSessionInfo), fluxos de trabalho (xtkWorkflow)

Para acessar as descrições de esquema na interface do Campaign, navegue até Administração > Configuração > Esquemas de dados, selecione um recurso e clique na guia Documentação.

Métodos do esquema de entidade entity-schema-methods

Cada esquema em Adobe Campaign (por exemplo, nms:recipient, nms:delivery) vem com métodos acessíveis por meio do objeto NLWS. Esses métodos fornecem uma maneira conveniente de interagir com entidades de banco de dados.

Métodos estáticos static-methods

Os métodos estáticos do SOAP são acessados chamando um método no objeto que representa o esquema. Por exemplo, NLWS.xtkWorkflow.PostEvent() invoca um método estático.

Métodos não estáticos non-static-methods

Para usar métodos SOAP não estáticos, você deve primeiro recuperar uma entidade usando os métodos load ou create nos esquemas correspondentes. Saiba mais na documentação JSAPI do Campaign.

Carregar, salvar e criar entidades load-save-create

Carregar uma entidade por ID e atualizá-la:

// Load a delivery by @id and save
var delivery = NLWS.nmsDelivery.load("12435");
delivery.label = "New label";
delivery.save();

Criar um destinatário usando JSON:

// Create via JSON, edit via JS and save
var recipient = NLWS.nmsRecipient.create({
  x: { // the key 'x' doesn't matter
    email: 'john.doe@example.com',
  }
});
recipient.folder_id = 1183;
recipient.firstName = 'John';
recipient.lastName = 'Doe';
recipient.save();

Criar um destinatário usando XML:

// Create via XML and save
var recipient = NLWS.nmsRecipient.create(
  <recipient
    email="support@adobe.com"
    lastName="Adobe"
    firstName="Support"
  />
);
recipient.save();

Visão geral de QueryDef querydef-overview

O esquema xtk:queryDef fornece métodos para compilar e executar consultas ao banco de dados. Você pode usar NLWS.xtkQueryDef.create() para criar consultas com sintaxe JSON ou XML.

Operações disponíveis:

  • select - Recuperar vários registros
  • get - Recuperar um único registro (SQL LIMIT 1)
  • getIfExists - Recuperar um único registro, retornar nulo se não for encontrado
  • count - Contar registros que correspondem aos critérios

Saiba mais sobre os métodos queryDef na documentação do Campaign JSAPI.

Consulta com JSON query-json

Use NLWS.xtkQueryDef.create() para criar consultas com sintaxe JSON. A operação get recupera um único registro (SQL LIMIT 1), enquanto select recupera vários registros.

Obter um único destinatário:

var email = "contact@example.com";
var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "get", // "get" does a SQL "LIMIT 1"
    select: {
      node: [{expr: "@id"}, {expr: "@email"}, {expr: "@firstName"}]
    },
    where: {
      condition: [
        {expr: "@email = '" + email + "'"}, // filter by email
      ],
    }
  }
});

var res = query.ExecuteQuery();
// res is an XML object such as <recipient id="1234" email="contact@example.com" firstName="John"/>
var recipient = NLWS.nmsRecipient.load(res.$id); // conversion to a JavaScript object
recipient.email = "newemail@example.com";
recipient.save();

Use getIfExists para evitar exceções:

Se o registro talvez não exista, use operation: "getIfExists" em vez de get para evitar exceções:

var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "getIfExists",
    select: { node: [{expr: "@id"}] },
    where: {
      condition: [{expr: "@email = 'nonexistent@example.com'"}]
    }
  }
});

var res = query.ExecuteQuery();
if (res) {
  logInfo("Recipient found: " + res.$id);
} else {
  logInfo("Recipient not found");
}

Selecionar vários registros select-multiple

Use a operação select para recuperar vários registros. Você pode adicionar condições, ordenação e limites.

Fluxos de trabalho de consulta com filtros e ordenação:

var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "xtk:workflow",
    operation: "select",
    select: {
      node: [
        {expr: "@id"},
        {expr: "@label"},
        {expr: "@internalName"}
      ]
    },
    where: {
      condition: [
        {expr: "[folder/@name]='nmsTechnicalWorkflow'"},
        {expr: "@production = 1"}
      ]
    },
    orderBy: {
      node: {expr: "@internalName", sortDesc: "false"}
    }
  }
});

var res = query.ExecuteQuery();

var workflows = res.getElementsByTagName("workflow");
for each (var w in workflows) {
  logInfo(w.getAttribute("internalName"));
}

Consultar entregas com sintaxe XML:

var q = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:delivery" operation="select" lineCount="3">
    <select>
      <node expr="@id"/>
      <node expr="@label"/>
      <node expr="@created"/>
    </select>
    <where>
      <condition expr="@label NOT LIKE '%Proof%'" bool-operator="AND"/>
      <condition expr="@created &lt;= '2024-12-01'" bool-operator="AND"/>
    </where>
    <orderBy>
      <node expr="@lastModified" sortDesc="true"/>
    </orderBy>
  </queryDef>
);

var deliveries = q.ExecuteQuery();
for each(var delivery in deliveries.delivery) {
  logInfo(delivery.@id + ": " + delivery.@label);
}
NOTE
Limites de resultado: o Campaign limita automaticamente os resultados da consulta para evitar problemas de memória:
  • O limite padrão varia de acordo com o contexto (normalmente de 200 a 10.000 registros)
  • Use lineCount para definir explicitamente o número máximo de resultados
  • Para conjuntos de dados grandes (>1000 registros), use workflows em vez de queryDef. Os workflows foram projetados para processar milhões de linhas com eficiência.

Saiba mais sobre ExecuteQuery e práticas recomendadas de consulta.

Consultar dados de transição do fluxo de trabalho workflow-transition-data

Ao trabalhar com atividades JavaScript em fluxos de trabalho, você pode consultar dados de transições de entrada usando vars.targetSchema e vars.tableName.

Consultar dados do destinatário de uma transição de fluxo de trabalho:

// Query data from the incoming transition
var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: vars.targetSchema, // The schema from the previous activity
    operation: 'select',
    lineCount: 999999999, // Override default 10,000 limit
    select: {
      node: [
        {expr: '@id'},
        {expr: '@email'},
        {expr: '@firstName'},
        {expr: '@lastName'}
      ]
    },
  }
});

var records = query.ExecuteQuery(); // Returns a DOMElement

for each(var record in records.getElements()) {
  logInfo("Processing: " + record.$id + " - " + record.$email);

  // Clean email address
  var cleanedEmail = record.$email.replace(/\s+/g, '').toLowerCase();

  // Update using parameterized query to prevent SQL injection
  sqlExec(
    "UPDATE " + vars.tableName + " SET sEmail=$(sz) WHERE iId=$(l)",
    cleanedEmail,
    record.$id
  );
}
CAUTION
Sempre use consultas parametrizadas com $(sz) para cadeias de caracteres e $(l) para números inteiros a fim de evitar vulnerabilidades de injeção de SQL. Saiba mais na documentação JSAPI do Campaign.

Contar registros count-records

Use Count(@id) com um alias para contar registros.

Contar hipóteses em execução:

var jobCount = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:remaHypothesis" operation="get">
    <select>
      <node expr="Count(@id)" alias="@count"/>
    </select>
    <where>
      <condition expr={"@status=" + HYPOTHESIS_STATUS_RUNNING}/>
    </where>
  </queryDef>
);

var iJobCount = parseInt(jobCount.ExecuteQuery().@count);
logInfo("Running jobs: " + iJobCount);

Contagem com várias condições:

var xmlQuery = <queryDef schema="nms:trackingLogRcp" operation="select">
  <select>
    <node expr="DateOnly(@logDate)" groupBy="1"/>
    <node expr="count(@id)" alias="@count"/>
    <node expr="countDistinct([@broadLog-id])" alias="@distinctCount"/>
  </select>
  <where>
    <condition expr={"@logDate IS NOT NULL AND @logDate &lt; #" + today + "# AND [@url-id] &lt;&gt; 1"}/>
  </where>
</queryDef>;

var result = NLWS.xtkQueryDef.create(xmlQuery).ExecuteQuery();

Distribuição de valores distribution-values

Obtenha a distribuição de valores para um campo específico, útil para analisar padrões de dados.

Distribuição de códigos de país:

/**
 * @class DistributionOfValues
 * @param {string} schema - The schema name (e.g., 'nms:recipient')
 * @param {string} field - The field to analyze (e.g., '@country')
 */
function DistributionOfValues(schema, field) {
  this.queryDef = {
    operation: 'select',
    lineCount: 200,
    schema: schema,
    select: {
      node: [
        {alias: '@expr', expr: field, groupBy: 'true', noSqlBind: 'true'},
        {alias: '@count', expr: 'COUNT()', label: 'Count'},
      ]
    },
    orderBy: {
      node: [{expr: 'COUNT()', sortDesc: 'true'}]
    },
  };

  /**
   * Execute the query and return results
   * @return {Array} XML list of results
   */
  this.get = function() {
    this.results = NLWS.xtkQueryDef.create({queryDef: this.queryDef}).ExecuteQuery();
    return this.results.getElements();
  };
}

// Usage example
var d = new DistributionOfValues('nms:recipient', '@country');

// Optional: Add additional filters
d.queryDef.where = {
  condition: [{expr: 'DateOnly(@created) = #2024-12-01#'}]
};

// Execute and display results
for each(var result in d.get()) {
  logInfo(result.$expr + ': ' + result.$count);
}

Enumerações de consulta com análise analyze-enumerations

A opção analyze retorna nomes amigáveis para valores de enumeração. Em vez de apenas valores numéricos, o Campaign também retornará o valor da string e o rótulo usando os sufixos "Nome" e "Rótulo".

Mapeamento de entrega de consulta com análise de enumeração:

var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:deliveryMapping",
    operation: "get",
    select: {
      node: [
        {expr: "@id"},
        {expr: "@name"},
        {expr: "[storage/@exclusionType]", analyze: true}  // Analyze enumeration
      ]
    },
    where: {
      condition: [{expr: "@name='mapRecipient'"}]
    }
  }
});

var mapping = query.ExecuteQuery();

// Result includes:
// - exclusionType: 2 (numeric value)
// - exclusionTypeName: "excludeRecipient" (string value)
// - exclusionTypeLabel: "Exclude recipient" (display label)
logInfo("Type: " + mapping.$exclusionType);
logInfo("Name: " + mapping.$exclusionTypeName);
logInfo("Label: " + mapping.$exclusionTypeLabel);

Saiba mais sobre a opção de análise.

Paginação pagination

Use lineCount e startLine para paginar por meio de conjuntos de resultados grandes.

Recuperar registros nas páginas:

// Get records 3 and 4 (skip first 2)
var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "select",
    lineCount: 2,     // Number of records per page
    startLine: 2,     // Starting position (0-indexed)
    select: {
      node: [
        {expr: "@id"},
        {expr: "@email"}
      ]
    },
    orderBy: {
      node: [{expr: "@id"}]  // Critical: Always use orderBy for pagination
    }
  }
});

var recipients = query.ExecuteQuery();
CAUTION
A paginação exige orderBy: sem uma cláusula orderBy, não há garantia de que os resultados da consulta estejam em uma ordem consistente. As chamadas subsequentes podem retornar páginas diferentes ou registros duplicados. Sempre inclua um orderBy ao usar paginação.

Saiba mais sobre paginação.

Construção de consulta dinâmica dynamic-queries

Criar consultas dinamicamente ao anexar condições de forma programática.

Anexar condições a uma consulta existente:

var xmlQuery = <queryDef schema="nms:delivery" operation="select">
  <select>
    <node expr="@id"/>
    <node expr="@label"/>
  </select>
  <where/>
</queryDef>;

// Dynamically add conditions
if (includeProofs) {
  xmlQuery.where.appendChild(
    <condition expr="@label LIKE '%Proof%'"/>
  );
}

if (startDate) {
  xmlQuery.where.appendChild(
    <condition expr={"@created >= #" + Format.toISO8601(startDate) + "#"}/>
  );
}

var result = NLWS.xtkQueryDef.create(xmlQuery).ExecuteQuery();

Criar cláusulas select e where em loops:

// Build select dynamically
var select = <select/>;
var fields = ["@id", "@label", "@created"];
for each(var field in fields) {
  select.appendChild(<node expr={field}/>);
}

// Build where dynamically
var where = <where/>;
var conditions = [
  "@status = 1",
  "@type = 'email'"
];
for each(var condition in conditions) {
  where.appendChild(<condition expr={condition}/>);
}

// Create complete query
var xmlQuery = <queryDef operation="select" schema="nms:delivery"/>;
xmlQuery.appendChild(select);
xmlQuery.appendChild(where);

var result = NLWS.xtkQueryDef.create(xmlQuery).ExecuteQuery();

Métodos queryDef avançados advanced-methods

Além de ExecuteQuery(), queryDef fornece vários métodos especializados para casos de uso avançados.

BuildQuery - Gerar SQL sem executar build-query

Use BuildQuery() para gerar a instrução SQL sem executá-la. Isso é útil para depurar, registrar ou transmitir consultas a sistemas externos.

var query = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:recipient" operation="select">
    <select>
      <node expr="@id"/>
      <node expr="@email"/>
    </select>
    <where>
      <condition expr="@email IS NOT NULL"/>
    </where>
  </queryDef>
);

// Get the generated SQL
var sql = query.BuildQuery();
logInfo("Generated SQL: " + sql);
// Output: "SELECT iRecipientId, sEmail FROM NmsRecipient WHERE sEmail IS NOT NULL"

Saiba mais sobre BuildQuery.

BuildQueryEx - Obter SQL com cadeia de caracteres de formato build-query-ex

BuildQueryEx() retorna a consulta SQL e uma cadeia de formato compatível com a função sqlSelect().

var query = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:recipient" operation="select">
    <select>
      <node expr="@id"/>
      <node expr="@email"/>
      <node expr="@firstName"/>
    </select>
  </queryDef>
);

var [sql, format] = query.BuildQueryEx();
logInfo("SQL: " + sql);
logInfo("Format: " + format);

// Use with sqlSelect
var results = sqlSelect(format, sql);

Saiba mais sobre BuildQueryEx.

Selecionar tudo - Adicione todos os campos para selecionar select-all

O método SelectAll() adiciona automaticamente todos os campos do esquema à cláusula select, evitando que você liste cada campo manualmente.

var query = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:recipient" operation="select">
    <select/>
    <where>
      <condition expr="@id = 12345"/>
    </where>
  </queryDef>
);

// Add all fields to the select
query.SelectAll(false);

var result = query.ExecuteQuery();
// Result contains all recipient fields

Saiba mais sobre SelectAll.

Atualizar - Registros de atualização em massa mass-update

O método Update() permite executar atualizações em massa nos registros correspondentes aos critérios de consulta sem carregar cada registro individualmente.

// Mass update example: set a field value for all matching records
var updateQuery = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "update",
    where: {
      condition: [{expr: "@country = 'US'"}]
    },
    set: {
      node: [{expr: "@blackList", value: "0"}]
    }
  }
});

// Execute mass update
updateQuery.Update();
logInfo("Mass update completed");
CAUTION
As atualizações em massa afetam todos os registros correspondentes à cláusula where. Sempre teste as condições where com uma consulta select primeiro para verificar quais registros serão afetados.

Saiba mais sobre Atualização.

GetInstanceFromModel - instâncias de modelo de consulta get-instance-from-model

Use GetInstanceFromModel() para recuperar dados de instâncias criadas a partir de modelos.

var query = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:delivery" operation="select">
    <select>
      <node expr="@id"/>
      <node expr="@label"/>
    </select>
    <where>
      <condition expr="@isModel = 1"/>
    </where>
  </queryDef>
);

// Get instance data from template
var instance = query.GetInstanceFromModel("nms:delivery");

Saiba mais sobre GetInstanceFromModel.

Operações em lote batch-operations

Processar vários registros em lote para melhorar o desempenho.

Rótulos de entrega de atualização em lote:

// Query all deliveries to update
var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: vars.targetSchema,
    operation: 'select',
    lineCount: 999999999,
    select: {
      node: [{expr: '@id'}]
    },
    where: {
      condition: [{expr: "@label LIKE '%OLD%'"}]
    }
  }
});

var records = query.ExecuteQuery();

// Process each record
for each(var record in records.getElements()) {
  var delivery = NLWS.nmsDelivery.load(record.$id);
  var oldLabel = delivery.label.toString();
  var newLabel = oldLabel.replace(/OLD/g, 'NEW');

  logInfo("Updating: " + oldLabel + " => " + newLabel);

  delivery.label = newLabel;
  delivery.save();
}

logInfo("Updated " + records.getElements().length + " deliveries");

Execução de SQL bruta raw-sql

Para operações complexas, você pode executar SQL bruto diretamente.

Executar SQL com parâmetros:

var dbEngine = instance.engine;

// Using parameterized query (recommended)
dbEngine.exec(
  "UPDATE NmsUserAgentStats SET iVisitorsOfTheDay=$(l) WHERE tsDate=$(dt)",
  visitorCount,
  Format.parseDateTimeInter(dateString)
);

Consulta com sqlSelect:

// Execute SELECT query and parse results
var xml = sqlSelect(
  "collection,@id,@email",
  "SELECT iId as id, sEmail as email FROM " + vars.tableName + " WHERE iStatus = 1"
);

logInfo(xml.toXMLString()); // "<select><collection id="1" email="..."/></select>"

for each(var record in xml.collection) {
  logInfo('ID: ' + record.@id + ', Email: ' + record.@email);

  // Load full object if needed
  if (vars.targetSchema == "nms:recipient") {
    var recipient = NLWS.nmsRecipient.load(record.@id);
    recipient.lastName = recipient.lastName.toUpperCase();
    recipient.save();
  }
}
CAUTION
Ao usar SQL bruto:
  • Sempre validar e limpar entradas de usuário
  • Use consultas parametrizadas com $(sz), $(l), $(dt) etc.
  • Esteja ciente das diferenças entre os bancos de dados local e em nuvem em implantações do FFDA

Práticas recomendadas best-practices

Ao trabalhar com os métodos queryDef e NLWS:

  • Usar fluxos de trabalho para conjuntos de dados grandes - QueryDef não foi projetado para processamento de dados de alto volume. Para conjuntos de dados com mais de 1.000 registros, use fluxos de trabalho que podem lidar com milhões de linhas com eficiência. Saiba mais na documentação do Campaign SDK
  • Usar consultas com parâmetros - Sempre usar parâmetros associados ($(sz), $(l)) com sqlExec para impedir a injeção de SQL
  • Definir limites explícitos - Use lineCount para controlar o tamanho do resultado. Os limites padrão do Campaign variam de acordo com o contexto (200-10.000 registros)
  • Usar orderBy com paginação - Sempre incluir uma cláusula orderBy ao usar startLine e lineCount para garantir paginação consistente
  • Use getIfExists - Use operation: "getIfExists" quando os registros não existirem para evitar exceções
  • Use analisar para enumerações - Adicione analyze: true para selecionar nós e obter nomes e rótulos de enumeração amigáveis
  • Otimizar consultas - Adicione as condições where apropriadas para limitar os conjuntos de resultados
  • Processamento em lote - Processe vários registros em lotes para evitar problemas de memória e tempos limite
  • Reconhecimento de FFDA - Em implantações corporativas (FFDA), esteja ciente de que Campaign funciona com dois bancos de dados

Casos de uso prático use-cases

Depurar e registrar consultas debug-queries

Use BuildQuery() para inspecionar o SQL gerado antes da execução:

var query = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "select",
    select: { node: [{expr: "@id"}, {expr: "@email"}] },
    where: { condition: [{expr: "@blackList = 0"}] }
  }
});

// Log the SQL for debugging
var sql = query.BuildQuery();
logInfo("About to execute: " + sql);

// Now execute
var results = query.ExecuteQuery();

Duplicar um registro com SelectAll duplicate-record

Usar SelectAll() para copiar todos os campos ao duplicar registros:

// Query the original record
var query = NLWS.xtkQueryDef.create(
  <queryDef schema="nms:delivery" operation="get">
    <select/>
    <where>
      <condition expr="@id = 12345"/>
    </where>
  </queryDef>
);

// Select all fields for duplication
query.SelectAll(true); // true indicates duplication mode

var original = query.ExecuteQuery();

// Create a new delivery from the original
var newDelivery = NLWS.nmsDelivery.create(original);
newDelivery.label = original.@label + " (Copy)";
newDelivery.save();

Validar antes da atualização em massa validate-mass-update

Sempre visualizar registros afetados antes de executar atualizações em massa:

// Step 1: Preview what will be updated
var previewQuery = NLWS.xtkQueryDef.create({
  queryDef: {
    schema: "nms:recipient",
    operation: "select",
    select: { node: [{expr: "@id"}, {expr: "@email"}] },
    where: { condition: [{expr: "@country = 'US' AND @blackList = 1"}] }
  }
});

var preview = previewQuery.ExecuteQuery();
var count = preview.getElementsByTagName("recipient").length;
logInfo("About to update " + count + " recipients");

// Step 2: If count looks correct, proceed with mass update
if (count > 0 && count < 10000) {
  sqlExec("UPDATE NmsRecipient SET iBlackList = 0 WHERE sCountryCode = 'US' AND iBlackList = 1");
  logInfo("Mass update completed for " + count + " recipients");
} else {
  logWarning("Update cancelled: count is " + count);
}

Referência da sintaxe da definição de consulta querydef-reference

Estrutura completa do objeto queryDef:

{
  queryDef: {
    schema: 'nms:recipient',           // Required: target schema
    operation: 'select',                // select|get|getIfExists|count
    lineCount: 100,                    // Maximum records to return
    startLine: 0,                      // Offset for pagination
    select: {
      node: [
        {
          expr: '@id',                 // XPath expression
          alias: '@myAlias',           // Optional alias
          label: 'ID',                 // Optional label
          groupBy: 'true',             // Group by this field
          noSqlBind: 'true'            // No SQL binding on constants
        }
      ]
    },
    where: {
      condition: [
        {
          expr: '@email IS NOT NULL',  // Condition expression
          boolOperator: 'AND',         // AND|OR
          setOperator: 'EXISTS',       // EXISTS|NOT EXISTS|IN|NOT IN
          enabledIf: '',               // Enabling condition
          ignore: false,               // Ignore this condition
          sql: '',                     // Native SQL expression
          'filter-name': ''            // Predefined filter name
        }
      ]
    },
    orderBy: {
      node: [
        {
          expr: '@lastModified',       // Field to sort by
          sortDesc: 'true'             // true for DESC, false for ASC
        }
      ]
    },
    groupBy: {
      node: [
        {expr: '@country'}             // Group by field
      ]
    }
  }
}
recommendation-more-help
35662671-8e3d-4f04-a092-029a056c566b