_ne 操作符数组支持
js-lite-rest 增强了 _ne (not equal) 操作符,现在支持数组值,让你能够一次性排除多个值,使查询更加灵活和高效。
概述
_ne 操作符现在支持两种使用方式:
- 单值排除:
field_ne: value- 排除单个值 - 多值排除:
field_ne: [value1, value2, ...]- 排除数组中的所有值
基本语法
javascript
// 单值排除(原有功能)
await store.get('table', { field_ne: 'value' });
// 多值排除(新增功能)
await store.get('table', { field_ne: ['value1', 'value2', 'value3'] });使用示例
数据准备
javascript
import JsLiteRest from 'js-lite-rest';
const store = await JsLiteRest.create({
books: [
{ id: 1, title: 'JavaScript权威指南', category: 'programming', status: 'available' },
{ id: 2, title: 'CSS揭秘', category: 'design', status: 'borrowed' },
{ id: 3, title: 'HTML5权威指南', category: 'markup', status: 'available' },
{ id: 4, title: 'Python编程', category: 'programming', status: 'maintenance' },
{ id: 5, title: 'Vue.js实战', category: 'programming', status: 'available' },
{ id: 6, title: 'React进阶', category: 'programming', status: 'borrowed' }
],
users: [
{ id: 1, name: 'Alice', role: 'admin', department: 'IT' },
{ id: 2, name: 'Bob', role: 'user', department: 'Sales' },
{ id: 3, name: 'Charlie', role: 'moderator', department: 'IT' },
{ id: 4, name: 'David', role: 'user', department: 'Marketing' },
{ id: 5, name: 'Eve', role: 'user', department: 'IT' }
]
});单值排除
javascript
// 排除特定类别
const nonProgrammingBooks = await store.get('books', {
category_ne: 'programming'
});
console.log(nonProgrammingBooks);
// [
// { id: 2, title: 'CSS揭秘', category: 'design', status: 'borrowed' },
// { id: 3, title: 'HTML5权威指南', category: 'markup', status: 'available' }
// ]
// 排除特定状态
const notBorrowedBooks = await store.get('books', {
status_ne: 'borrowed'
});
console.log(notBorrowedBooks);
// 返回状态不是 'borrowed' 的所有书籍多值排除(数组支持)
javascript
// 排除多个类别
const excludeMultipleCategories = await store.get('books', {
category_ne: ['programming', 'design']
});
console.log(excludeMultipleCategories);
// [
// { id: 3, title: 'HTML5权威指南', category: 'markup', status: 'available' }
// ]
// 排除多个状态
const availableOrMaintenanceBooks = await store.get('books', {
status_ne: ['borrowed', 'maintenance']
});
console.log(availableOrMaintenanceBooks);
// 返回状态为 'available' 的所有书籍
// 排除多个用户角色
const nonRegularUsers = await store.get('users', {
role_ne: ['user', 'guest']
});
console.log(nonRegularUsers);
// [
// { id: 1, name: 'Alice', role: 'admin', department: 'IT' },
// { id: 3, name: 'Charlie', role: 'moderator', department: 'IT' }
// ]数字和 ID 排除
javascript
// 排除特定 ID
const excludeSpecificBooks = await store.get('books', {
id_ne: [1, 3, 5]
});
console.log(excludeSpecificBooks);
// 返回 id 不是 1, 3, 5 的书籍
// 排除多个用户
const excludeUsers = await store.get('users', {
id_ne: [2, 4]
});
console.log(excludeUsers);
// 返回 id 不是 2, 4 的用户高级用法
与其他条件组合
javascript
// 组合查询:获取编程类别中状态不是借出或维护的书籍
const availableProgrammingBooks = await store.get('books', {
category: 'programming',
status_ne: ['borrowed', 'maintenance']
});
console.log(availableProgrammingBooks);
// [
// { id: 1, title: 'JavaScript权威指南', category: 'programming', status: 'available' },
// { id: 5, title: 'Vue.js实战', category: 'programming', status: 'available' }
// ]
// 组合查询:获取 IT 部门中角色不是普通用户的员工
const itNonUsers = await store.get('users', {
department: 'IT',
role_ne: ['user']
});
console.log(itNonUsers);
// [
// { id: 1, name: 'Alice', role: 'admin', department: 'IT' },
// { id: 3, name: 'Charlie', role: 'moderator', department: 'IT' }
// ]与其他操作符组合
javascript
// 组合 _ne 和 _gte
const recentBooksExcludingCategories = await store.get('books', {
id_gte: 3,
category_ne: ['design', 'markup']
});
// 组合 _ne 和 _like
const programBooksExcludingSpecific = await store.get('books', {
title_like: 'JavaScript|Vue|React',
status_ne: ['borrowed', 'maintenance']
});深层字段排除
javascript
// 假设有嵌套数据结构
const store2 = await JsLiteRest.create({
products: [
{ id: 1, name: 'Laptop', specs: { brand: 'Dell', color: 'black' } },
{ id: 2, name: 'Mouse', specs: { brand: 'Logitech', color: 'white' } },
{ id: 3, name: 'Keyboard', specs: { brand: 'Apple', color: 'silver' } },
{ id: 4, name: 'Monitor', specs: { brand: 'Dell', color: 'black' } }
]
});
// 排除多个品牌
const nonDellLogitech = await store2.get('products', {
'specs.brand_ne': ['Dell', 'Logitech']
});
console.log(nonDellLogitech);
// [
// { id: 3, name: 'Keyboard', specs: { brand: 'Apple', color: 'silver' } }
// ]
// 排除多个颜色
const colorExclusion = await store2.get('products', {
'specs.color_ne': ['black', 'white']
});
console.log(colorExclusion);
// [
// { id: 3, name: 'Keyboard', specs: { brand: 'Apple', color: 'silver' } }
// ]边界情况处理
空数组
javascript
// 空数组不排除任何值
const allBooks = await store.get('books', {
category_ne: []
});
console.log(allBooks.length); // 返回所有书籍不存在的值
javascript
// 数组中包含不存在的值不会影响结果
const booksExcludingNonexistent = await store.get('books', {
category_ne: ['programming', 'nonexistent', 'design']
});
// 等同于 category_ne: ['programming', 'design']类型混合
javascript
// 可以在数组中混合不同类型的值
const mixedExclusion = await store.get('books', {
id_ne: [1, '2', 3] // 数字和字符串混合
});
// 会正确排除 id 为 1, 2, 3 的记录(自动类型转换)性能考虑
索引优化
javascript
// 对于大型数据集,考虑查询的效率
// 推荐:先用其他条件过滤,再用 _ne 排除
const efficientQuery = await store.get('books', {
category: 'programming', // 先过滤主要条件
status_ne: ['borrowed'] // 再排除不需要的
});
// 避免:只用 _ne 进行大范围排除
const inefficientQuery = await store.get('books', {
id_ne: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 大量排除可能效率较低
});内存使用
javascript
// 对于超大数组,考虑分批处理
async function excludeManySafely(table, field, excludeArray) {
if (excludeArray.length > 100) {
console.warn('排除数组较大,建议考虑重新设计查询策略');
}
return await store.get(table, {
[`${field}_ne`]: excludeArray
});
}实际应用场景
1. 内容过滤系统
javascript
async function getFilteredContent(excludedCategories, excludedStatuses) {
return await store.get('articles', {
category_ne: excludedCategories,
status_ne: excludedStatuses,
published: true
});
}
// 使用示例
const safeContent = await getFilteredContent(
['adult', 'violence', 'politics'],
['draft', 'deleted', 'suspended']
);2. 用户权限管理
javascript
async function getUsersExcludingRoles(excludedRoles, department = null) {
const query = {
role_ne: excludedRoles,
active: true
};
if (department) {
query.department = department;
}
return await store.get('users', query);
}
// 获取除了管理员和超级用户外的所有活跃用户
const regularUsers = await getUsersExcludingRoles(['admin', 'superuser']);
// 获取 IT 部门中除了实习生的所有用户
const itUsers = await getUsersExcludingRoles(['intern'], 'IT');3. 商品筛选
javascript
async function getProductsExcludingBrands(excludedBrands, priceRange = null) {
const query = {
'brand_ne': excludedBrands,
'available': true
};
if (priceRange) {
query['price_gte'] = priceRange.min;
query['price_lte'] = priceRange.max;
}
return await store.get('products', query);
}
// 排除特定品牌,价格在指定范围内的商品
const filteredProducts = await getProductsExcludingBrands(
['BrandA', 'BrandB', 'BrandC'],
{ min: 100, max: 1000 }
);4. 数据清洗
javascript
async function cleanData() {
// 排除测试数据和无效数据
const cleanUsers = await store.get('users', {
email_ne: ['test@test.com', 'admin@test.com'],
status_ne: ['deleted', 'suspended', 'test']
});
// 排除草稿和已删除的文章
const validArticles = await store.get('articles', {
status_ne: ['draft', 'deleted', 'spam']
});
return {
users: cleanUsers,
articles: validArticles
};
}与传统方法的对比
使用 _ne 数组(推荐)
javascript
// 简洁明了
const result = await store.get('books', {
category_ne: ['programming', 'design', 'markup']
});传统方法(不推荐)
javascript
// 需要多次查询或复杂逻辑
const allBooks = await store.get('books');
const result = allBooks.filter(book =>
!['programming', 'design', 'markup'].includes(book.category)
);注意事项
- 数组长度: 虽然支持任意长度的数组,但过长的排除列表可能影响性能
- 类型转换: 比较时会进行自动类型转换,确保数据类型一致性
- 空值处理:
null和undefined会被正确处理 - 内存占用: 大型排除数组会增加内存使用量