如何查找含空值/空白字段及数组内异常字段的记录?
RethinkDB迁移时数组对象字段校验解决方案
需求说明
我们正在从RethinkDB迁移到关系型数据库,部分遗留表因多次结构变更,存在以下异常记录需要排查:
- 普通字段为空值、空白内容或格式错误(比如
count字段应为数字却存了字符串) - 数组(如示例中的
my_arr)内对象存在缺失字段、空白字段,且数组内所有对象的字段必须完全一致
目前已有处理普通字段的过滤语句:.hasFields('field_name').not().or(doc('field_name').eq('')),但无法覆盖数组内对象的校验场景,以下是针对性解决方法。
示例记录:
{ "name": "bob", "details": { "inside_details": "the details", "my_arr": [ { "field1": "val1", "field2": "val2" } ] }, "count": 1 }
分步解决方案
1. 检测数组内对象的缺失/空白字段
针对my_arr数组,通过遍历元素检查必填字段是否存在且非空白:
// 筛选my_arr中存在缺失field1/field2,或字段值为空的记录 r.table('your_table').filter(doc => { // 先确保my_arr存在且为数组类型 const arrValid = doc.hasFields('details', 'my_arr').and(doc('details')('my_arr').typeOf().eq('ARRAY')); return arrValid.and( doc('details')('my_arr').forEach(item => { return item.hasFields('field1', 'field2') .and(item('field1').ne('')) .and(item('field2').ne('')); }).not() // 取反,找出不符合校验条件的记录 ); });
2. 检测数组内对象字段一致性
确保数组内所有对象的字段完全一致,可通过对比第一个元素与其他元素的字段集合实现:
// 筛选my_arr内对象字段不一致的记录 r.table('your_table').filter(doc => { const arr = doc('details')('my_arr'); const arrValid = doc.hasFields('details', 'my_arr').and(arr.typeOf().eq('ARRAY')).and(arr.count().gt(1)); return arrValid.and( // 第一个元素的字段集合与后续所有元素的共同字段集合存在差异 arr.nth(0).keys().setDifference( arr.slice(1) .forEach(item => item.keys()) .reduce((acc, keys) => acc.setIntersection(keys), arr.nth(0).keys()) ).count().gt(0) ); });
3. 整合所有校验逻辑
将普通字段校验与数组校验合并,一次性排查所有异常记录:
r.table('your_table').filter(doc => { // 普通字段校验:示例检查name非空、count为数字类型 const normalErrors = doc('name').eq('') .or(doc('count').typeOf().ne('NUMBER')) .or(doc.hasFields('name').not()); // 数组相关校验 const arr = doc('details')('my_arr'); const arrValid = doc.hasFields('details', 'my_arr').and(arr.typeOf().eq('ARRAY')); // 数组元素字段缺失/空白 const arrItemErrors = arrValid.and( arr.forEach(item => { return item.hasFields('field1', 'field2') .and(item('field1').ne('')) .and(item('field2').ne('')); }).not() ); // 数组内对象字段不一致 const arrFieldConsistencyErrors = arrValid.and(arr.count().gt(1)).and( arr.nth(0).keys().setDifference( arr.slice(1) .forEach(item => item.keys()) .reduce((acc, keys) => acc.setIntersection(keys), arr.nth(0).keys()) ).count().gt(0) ); // 满足任意异常条件即返回 return normalErrors.or(arrItemErrors).or(arrFieldConsistencyErrors); });
注意事项
- 替换代码中的
your_table为实际表名,field1、field2为数组对象的必填字段 - 可根据实际需求扩展校验规则,比如增加特定格式校验(如日期、邮箱)或更多普通字段的检查
内容的提问来源于stack exchange,提问作者Brunaldo
相关产品推荐
相关产品推荐

