使用queryDef查詢資料庫 query-database-api
Adobe Campaign提供強大的JavaScript方法,以使用queryDef和NLWS物件與資料庫互動。 這些以SOAP為基礎的方法可讓您使用JSON、XML或SQL載入、建立、更新和查詢資料。
什麼是NLWS? what-is-nlws
NLWS (Neolane Web Services)是全域JavaScript物件,用來存取Adobe Campaign的SOAP型API方法。 結構描述是NLWS物件的屬性,可讓您以程式設計方式與Campaign實體互動。
根據Campaign JSAPI檔案,「結構描述是'NLWS'全域物件。」 存取結構描述方法的語法遵循以下模式:
NLWS.<namespace><SchemaName>.<method>()
範例:
NLWS.nmsRecipient— 收件者結構描述(nms:recipient)的存取方法NLWS.nmsDelivery— 傳遞結構描述(nms:delivery)的存取方法NLWS.xtkQueryDef— 存取查詢資料庫的queryDef方法
常見的API方法包括:
load(id)— 依實體識別碼載入實體。 了解更多create(data)— 建立新實體save()— 儲存對實體的變更
官方檔案中的範例:
var delivery = NLWS.nmsDelivery.load("12435")
nms.recipient.create()、xtk.queryDef.create())。 兩種語法都有效,但NLWS是官方Campaign JSAPI參考中記錄的標準。先決條件 prerequisites
在使用queryDef和NLWS方法之前,您應該先熟悉:
- JavaScript
- Adobe Campaign資料模型和結構描述
- 用於導覽結構描述元素的XPath運算式
瞭解Campaign資料模型:
Adobe Campaign隨附預先定義的資料模型,其中包含連結在雲端資料庫中的表格。 基本結構包括:
-
收件者資料表 (
nmsRecipient) — 儲存行銷設定檔的主資料表 -
傳遞資料表 (
nmsDelivery) — 以執行傳遞的引數儲存傳遞動作和範本 -
記錄資料表 — 儲存執行記錄檔:
nmsBroadLogRcp— 傳送給收件者的所有訊息的傳遞記錄nmsTrackingLogRcp— 追蹤收件者回應的記錄(開啟、點按)
-
技術資料表 — 儲存系統資料,例如運運算元(
xtkGroup)、工作階段(xtkSessionInfo)、工作流程(xtkWorkflow)
若要存取Campaign介面中的結構描述說明,請瀏覽至管理>設定>資料結構描述,選取資源,然後按一下 檔案 索引標籤。
實體結構描述方法 entity-schema-methods
Adobe Campaign (例如nms:recipient、nms:delivery)中的每個結構描述都包含可透過NLWS物件存取的方法。 這些方法提供了與資料庫實體互動的便利方式。
靜態方法 static-methods
靜態SOAP方法可透過在代表結構描述的物件上叫用方法來存取。 例如,NLWS.xtkWorkflow.PostEvent()會叫用靜態方法。
非靜態方法 non-static-methods
若要使用非靜態SOAP方法,您必須先使用對應結構描述上的load或create方法擷取實體。 在Campaign JSAPI檔案中瞭解更多。
載入、儲存及建立實體 load-save-create
依ID載入實體並更新它:
// Load a delivery by @id and save
var delivery = NLWS.nmsDelivery.load("12435");
delivery.label = "New label";
delivery.save();
使用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();
使用XML建立收件者:
// Create via XML and save
var recipient = NLWS.nmsRecipient.create(
<recipient
email="support@adobe.com"
lastName="Adobe"
firstName="Support"
/>
);
recipient.save();
QueryDef概述 querydef-overview
xtk:queryDef結構描述提供建立和執行資料庫查詢的方法。 您可以使用NLWS.xtkQueryDef.create()來建立具有JSON或XML語法的查詢。
可用的作業:
select— 擷取多個記錄get— 擷取單一記錄(SQLLIMIT 1)getIfExists— 擷取單一記錄,如果找不到,則傳回nullcount— 計算符合條件的記錄
在Campaign JSAPI檔案中進一步瞭解queryDef方法。
使用JSON查詢 query-json
使用NLWS.xtkQueryDef.create()以JSON語法建置查詢。 get作業會擷取單一記錄(SQL LIMIT 1),而select會擷取多個記錄。
取得單一收件者:
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();
使用getIfExists以避免例外狀況:
如果記錄可能不存在,請使用operation: "getIfExists"而非get以避免例外狀況:
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");
}
選取多個記錄 select-multiple
使用select作業擷取多個記錄。 您可以新增條件、順序和限制。
具有篩選和排序的查詢工作流程:
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"));
}
使用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 <= '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);
}
- 預設限制因內容而異(通常為200至10,000筆記錄)
- 使用
lineCount明確設定結果數目上限 - 對於大型資料集(超過1000筆記錄),請使用工作流程而不是queryDef。 工作流程的設計宗旨是有效率地處理數百萬列。
深入瞭解ExecuteQuery和查詢最佳實務。
查詢工作流程轉變資料 workflow-transition-data
在工作流程中使用JavaScript活動時,您可以使用vars.targetSchema和vars.tableName來查詢傳入轉變的資料。
從工作流程轉換查詢收件者資料:
// 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
);
}
計算記錄 count-records
使用具有別名的Count(@id)來計算記錄。
計算執行中的假設:
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);
包含多個條件的計數:
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 < #" + today + "# AND [@url-id] <> 1"}/>
</where>
</queryDef>;
var result = NLWS.xtkQueryDef.create(xmlQuery).ExecuteQuery();
值的分佈 distribution-values
取得特定欄位的值分佈,用於分析資料模式。
國家/地區代碼的分佈:
/**
* @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);
}
使用分析查詢分項清單 analyze-enumerations
analyze選項會傳回列舉值的好記名稱。 Campaign也將使用「Name」和「Label」尾碼來傳回字串值和標籤,而不只是數值。
具有列舉分析的查詢傳遞對應:
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);
深入瞭解分析選項。
分頁 pagination
使用lineCount和startLine在大型結果集中分頁。
擷取頁面中的記錄:
// 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();
orderBy子句,無法保證查詢結果的順序一致。 後續呼叫可能會傳回不同頁面或重複記錄。 使用分頁時一律包括orderBy。深入瞭解分頁。
動態查詢建構 dynamic-queries
以程式設計方式附加條件,以動態方式建立查詢。
將條件附加至現有查詢:
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();
在回圈中建置select和where子句:
// 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();
進階queryDef方法 advanced-methods
在ExecuteQuery()之外,queryDef為進階使用案例提供數種專門的方法。
BuildQuery — 產生SQL而不執行 build-query
使用BuildQuery()產生SQL陳述式而不執行它。 這對於偵錯、記錄或將查詢傳遞至外部系統非常有用。
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"
深入瞭解BuildQuery。
BuildQueryEx — 取得具有格式字串的SQL build-query-ex
BuildQueryEx()會傳回SQL查詢和與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);
深入瞭解BuildQueryEx。
SelectAll — 新增要選取的所有欄位 select-all
SelectAll()方法會自動將結構描述中的所有欄位新增到select子句中,讓您不會手動列出每個欄位。
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
深入瞭解全選。
更新 — 整批更新記錄 mass-update
Update()方法可讓您對符合查詢條件的記錄執行大量更新,而不需個別載入每個記錄。
// 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");
深入瞭解更新。
GetInstanceFromModel — 查詢範本執行個體 get-instance-from-model
使用GetInstanceFromModel()從範本建立的執行個體擷取資料。
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");
深入瞭解GetInstanceFromModel。
批次作業 batch-operations
批次處理多個記錄以提高效能。
批次更新傳遞標籤:
// 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");
原始SQL執行 raw-sql
對於複雜的作業,您可以直接執行原始SQL。
執行引數化SQL:
var dbEngine = instance.engine;
// Using parameterized query (recommended)
dbEngine.exec(
"UPDATE NmsUserAgentStats SET iVisitorsOfTheDay=$(l) WHERE tsDate=$(dt)",
visitorCount,
Format.parseDateTimeInter(dateString)
);
使用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();
}
}
最佳實務 best-practices
使用queryDef和NLWS方法時:
- 針對大型資料集使用工作流程 - QueryDef並非針對大量資料處理而設計。 針對擁有超過1,000筆記錄的資料集,請使用可有效處理數百萬列的工作流程。 在Campaign SDK檔案中進一步瞭解
- 使用引數化查詢 — 一律使用具有
$(sz)的繫結引數($(l),sqlExec)以防止SQL插入 - 設定明確限制 — 使用
lineCount控制結果大小。 行銷活動的預設限制依內容而異(200到10,000筆記錄) - 搭配分頁使用orderBy — 使用
orderBy和startLine時一律包含lineCount子句,以確保分頁一致 - 使用getIfExists — 在記錄可能不存在時使用
operation: "getIfExists"以避免例外狀況 - 使用分析列舉 — 新增
analyze: true以選取節點,以取得好記的列舉名稱和標籤 - 最佳化查詢 — 新增適當的
where條件以限制結果集 - 批次處理 — 以批次處理多個記錄以避免記憶體問題和逾時
- FFDA感知度 — 在企業(FFDA)部署中,請注意Campaign可搭配兩個資料庫使用
實際使用案例 use-cases
偵錯並記錄查詢 debug-queries
使用BuildQuery()在執行前檢查產生的SQL:
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();
使用SelectAll複製記錄 duplicate-record
複製記錄時使用SelectAll()複製所有欄位:
// 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();
大量更新前驗證 validate-mass-update
在執行整批更新之前,一律預覽受影響的記錄:
// 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);
}
查詢定義語法參考 querydef-reference
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
]
}
}
}