gliderecord-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GlideRecord Best Practices for ServiceNow

ServiceNow的GlideRecord最佳实践

GlideRecord is the primary API for database operations in ServiceNow. Following these patterns ensures efficient and secure queries.
GlideRecord是ServiceNow中用于数据库操作的核心API。遵循以下模式可确保查询高效且安全。

Basic Query Patterns

基础查询模式

Get Single Record by sys_id

通过sys_id获取单条记录

javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gs.info('Found: ' + gr.getValue('number'));
}
javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gs.info('Found: ' + gr.getValue('number'));
}

Get Single Record by Field

通过字段获取单条记录

javascript
var gr = new GlideRecord('sys_user');
if (gr.get('user_name', 'admin')) {
  gs.info('Found user: ' + gr.getValue('name'));
}
javascript
var gr = new GlideRecord('sys_user');
if (gr.get('user_name', 'admin')) {
  gs.info('Found user: ' + gr.getValue('name'));
}

Query Multiple Records

查询多条记录

javascript
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.addQuery('priority', '1');
gr.orderByDesc('sys_created_on');
gr.setLimit(100);
gr.query();

while (gr.next()) {
  gs.info(gr.getValue('number'));
}
javascript
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.addQuery('priority', '1');
gr.orderByDesc('sys_created_on');
gr.setLimit(100);
gr.query();

while (gr.next()) {
  gs.info(gr.getValue('number'));
}

Encoded Queries (Faster)

编码查询(更高效)

Use encoded queries for complex conditions - they're more efficient than multiple addQuery calls:
javascript
var gr = new GlideRecord('incident');
// Encoded query from list view URL or Query Builder
gr.addEncodedQuery('active=true^priority=1^assigned_toISEMPTY');
gr.query();

while (gr.next()) {
  // Process records
}
对于复杂条件,使用编码查询——它们比多次调用addQuery更高效:
javascript
var gr = new GlideRecord('incident');
// 来自列表视图URL或查询构建器的编码查询
gr.addEncodedQuery('active=true^priority=1^assigned_toISEMPTY');
gr.query();

while (gr.next()) {
  // 处理记录
}

Performance Tips

性能优化技巧

1. Always Use setLimit()

1. 始终使用setLimit()

javascript
// When you only need X records
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.setLimit(10);  // Don't fetch more than needed
gr.query();
javascript
// 当你只需要X条记录时
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.setLimit(10);  // 不要获取超出需求的记录
gr.query();

2. Use getValue() for Strings

2. 使用getValue()获取字符串

javascript
// CORRECT - Returns string value
var number = gr.getValue('number');

// ALSO WORKS but returns GlideElement
var element = gr.number;
var numberStr = gr.number.toString();
javascript
// 正确用法 - 返回字符串值
var number = gr.getValue('number');

// 也可使用,但返回GlideElement对象
var element = gr.number;
var numberStr = gr.number.toString();

3. Use getDisplayValue() for References

3. 使用getDisplayValue()获取引用字段的显示值

javascript
// Get the display value of a reference field
var assignedToName = gr.getDisplayValue('assigned_to');

// Get the sys_id of a reference field
var assignedToId = gr.getValue('assigned_to');
javascript
// 获取引用字段的显示值
var assignedToName = gr.getDisplayValue('assigned_to');

// 获取引用字段的sys_id
var assignedToId = gr.getValue('assigned_to');

4. Avoid Queries in Loops

4. 避免在循环中执行查询

javascript
// BAD - Query inside loop
for (var i = 0; i < userIds.length; i++) {
  var gr = new GlideRecord('sys_user');
  gr.get(userIds[i]);  // N queries!
}

// GOOD - Single query with IN clause
var gr = new GlideRecord('sys_user');
gr.addQuery('sys_id', 'IN', userIds.join(','));
gr.query();
while (gr.next()) {
  // Process all users at once
}
javascript
// 错误示例 - 循环内执行查询
for (var i = 0; i < userIds.length; i++) {
  var gr = new GlideRecord('sys_user');
  gr.get(userIds[i]);  // 会执行N次查询!
}

// 正确示例 - 使用IN子句单次查询
var gr = new GlideRecord('sys_user');
gr.addQuery('sys_id', 'IN', userIds.join(','));
gr.query();
while (gr.next()) {
  // 一次性处理所有用户
}

5. Use GlideAggregate for Counts

5. 使用GlideAggregate进行计数

javascript
// BAD - Counting with GlideRecord
var count = 0;
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.query();
while (gr.next()) {
  count++;
}

// GOOD - Use GlideAggregate
var ga = new GlideAggregate('incident');
ga.addQuery('active', true);
ga.addAggregate('COUNT');
ga.query();
if (ga.next()) {
  var count = ga.getAggregate('COUNT');
}
javascript
// 错误示例 - 使用GlideRecord计数
var count = 0;
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.query();
while (gr.next()) {
  count++;
}

// 正确示例 - 使用GlideAggregate
var ga = new GlideAggregate('incident');
ga.addQuery('active', true);
ga.addAggregate('COUNT');
ga.query();
if (ga.next()) {
  var count = ga.getAggregate('COUNT');
}

CRUD Operations

CRUD操作

Insert

插入记录

javascript
var gr = new GlideRecord('incident');
gr.initialize();
gr.setValue('short_description', 'New incident');
gr.setValue('caller_id', gs.getUserID());
gr.setValue('priority', '3');
var sysId = gr.insert();
javascript
var gr = new GlideRecord('incident');
gr.initialize();
gr.setValue('short_description', 'New incident');
gr.setValue('caller_id', gs.getUserID());
gr.setValue('priority', '3');
var sysId = gr.insert();

Update

更新记录

javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gr.setValue('state', '6');  // Resolved
  gr.setValue('close_notes', 'Issue fixed');
  gr.update();
}
javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gr.setValue('state', '6');  // 已解决
  gr.setValue('close_notes', 'Issue fixed');
  gr.update();
}

Delete (Use with Caution!)

删除记录(谨慎使用!)

javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gr.deleteRecord();
}
javascript
var gr = new GlideRecord('incident');
if (gr.get('sys_id_here')) {
  gr.deleteRecord();
}

Bulk Update

批量更新

javascript
var gr = new GlideRecord('incident');
gr.addQuery('state', '6');  // Resolved
gr.addQuery('resolved_at', '<', gs.daysAgoStart(30));
gr.query();

while (gr.next()) {
  gr.setValue('state', '7');  // Closed
  gr.update();
}
javascript
var gr = new GlideRecord('incident');
gr.addQuery('state', '6');  // 已解决
gr.addQuery('resolved_at', '<', gs.daysAgoStart(30));
gr.query();

while (gr.next()) {
  gr.setValue('state', '7');  // 已关闭
  gr.update();
}

Query Operators

查询操作符

OperatorExampleDescription
=
addQuery('active', true)
Equals
!=
addQuery('active', '!=', true)
Not equals
>
,
<
addQuery('priority', '<', '3')
Greater/Less than
>=
,
<=
addQuery('sys_created_on', '>=', gs.daysAgoStart(7))
Greater/Less or equal
CONTAINS
addQuery('short_description', 'CONTAINS', 'error')
Contains string
STARTSWITH
addQuery('number', 'STARTSWITH', 'INC')
Starts with
ENDSWITH
addQuery('email', 'ENDSWITH', '@company.com')
Ends with
IN
addQuery('state', 'IN', '1,2,3')
In list
NOT IN
addQuery('state', 'NOT IN', '6,7')
Not in list
ISEMPTY
addQuery('assigned_to', 'ISEMPTY', '')
Field is empty
ISNOTEMPTY
addQuery('assigned_to', 'ISNOTEMPTY', '')
Field is not empty
操作符示例描述
=
addQuery('active', true)
等于
!=
addQuery('active', '!=', true)
不等于
>
,
<
addQuery('priority', '<', '3')
大于/小于
>=
,
<=
addQuery('sys_created_on', '>=', gs.daysAgoStart(7))
大于等于/小于等于
CONTAINS
addQuery('short_description', 'CONTAINS', 'error')
包含指定字符串
STARTSWITH
addQuery('number', 'STARTSWITH', 'INC')
以指定内容开头
ENDSWITH
addQuery('email', 'ENDSWITH', '@company.com')
以指定内容结尾
IN
addQuery('state', 'IN', '1,2,3')
在指定列表中
NOT IN
addQuery('state', 'NOT IN', '6,7')
不在指定列表中
ISEMPTY
addQuery('assigned_to', 'ISEMPTY', '')
字段为空
ISNOTEMPTY
addQuery('assigned_to', 'ISNOTEMPTY', '')
字段不为空

Security Considerations

安全注意事项

  1. setWorkflow(false) - Skip business rules for bulk operations
  2. setLimit() - Prevent runaway queries
  3. Check canRead()/canWrite() - Verify ACL permissions
  4. Never trust user input - Validate before using in queries
  1. setWorkflow(false) - 批量操作时跳过业务规则
  2. setLimit() - 防止查询失控
  3. 检查canRead()/canWrite() - 验证ACL权限
  4. 绝不信任用户输入 - 在查询中使用前先验证输入内容