当通过hset 设置的key 的值为null 时,将其序列化为字符串“null”。 通过hgetall获取hash时,返回对象中对应的值为字符串“null”而不是null。
我意识到 node-redis 不会对从 redis 检索到的字符串值进行任何数据类型转换。 我隐含地假设布尔值、数字等会自动转换为相应的 javascript 类型。 如果您认为这不在项目范围内,请关闭问题。
但是,自动转换会很好。 我只是花了大量时间调试由于错误值被检索为“false”并通过 javascript 的真值检查条件而引起的错误。
是的,真假也是让我着迷的那个。
我实际上想在库中解决这个问题,尽管肯定存在性能问题。
@brycebaril我们可以向 JSON.stringify/parse 输入引入一个标志。 这应该是一个很好的解决方案,你不这么认为吗?
也许在 createClient 构造函数中有一个选项。 就像是...
_parse_bool_:将“真”转换为真,将“假”转换为假
_parse_null_:将“空”转换为空
但是,您将如何处理“true”和“null”的实际字符串值? 无法检测原始输入类型是什么。
@Azmisov正如@dirkbonhomme指出的那样,这不是一个好的解决方案。 因此,仅使用 JSON.stringify/parse 可能是一种选择。
我想不是在特定的命令库上而是针对所有命令来解决这个问题。 这样也没有性能损失,因为无论如何我们都会检查每个参数,更重要的是:无论您如何传递参数(数组、对象、参数),它都能解决任何命令。
如果任何命令包含未定义或空值,我更愿意返回错误。 这几乎总是表明传递的参数有问题。
有些人可能希望有一种方法来处理不同的未定义和/或空值,所以我会添加一个选项,您可以将函数传递给该选项,如果任何命令包含空/未定义值,则会触发此函数。
该函数始终获取命令名称和传递给它的参数,并且返回值将替换原始参数。 这样,任何用户都可以根据需要处理这些值。
相同的逻辑可以应用于真/假。
@NodeRedis/贡献者@dirkbonhomme你怎么看? :)
@BridgeAR我不同意null
是“有问题的迹象”。 采取这样的事情:
var myIndexes = ['one','two','three'], myMulti = client.multi();
myIndexes.forEach(function(aKey) {
myMulti.hget(aKey,'username');
myMulti.hget(aKey,'address1');
myMulti.hget(aKey,'address2');
});
myMulti.exec(cb);
假设 'address2' 在您的数据中是可选的,那么null
返回就可以了。
话虽如此,我认为这对许多人来说将是一个突破性的变化,所以像你提议的那样应该是可选的,而不是默认的。
@stockholmux我不确定我们是否谈论过同样的事情。 返回值不会以任何方式改变。
我想改变的是,使用null
将导致字符串'null'
代替:
client.set('foo', null);
client.get('foo', function (err, res) {
console.log(res); // 'null'
});
我也不会破坏任何东西,因为我打算弃用旧行为(有些人可能会通过围绕问题构建来依赖破坏行为)并添加选项来立即自行处理此问题并从v.3.0.0 用于此类值。
“空”值问题是否得到解决?
你会在你的程序中定义一个特殊的标记来代表真正的空值吗? 当用户将某些东西设置为空时,您捕获该命令并将空值替换为您的特殊标记。当用户获得该东西时,您捕获该命令并将特殊标记替换为真正的空值给用户?
只是一个建议。 这个问题真的很困扰。 因为任何站点中的任何用户都可能有一个名为 'null' 的名称,所以您不希望将用户名解析为真正的 null 值;
“JSON.{parse,stringify} on input”标志是否有任何进展或决定? 自动完成此操作而不是在任何给定的获取/设置逻辑中会很好。
嘿@taylorzane我现在没有时间,但它肯定计划实施。
听起来还不错。 如果我有一些时间可以尝试一下,那肯定会很好,而且我喜欢在我使用的模块源上进行黑客攻击。 :+1:
这现在有效吗?
我最终使用了一种不同的方法将数据序列化到 Redis 中,所以我从来没有考虑过实现这一点。
如果您不介意分享@taylorzane ,您将如何使用 Redis 将 JSON 对象存储在其内部可能具有空值的字段中
@slidenerd我正在展平 JSON 对象,然后在将其存储在 Redis 之前序列化每个展平的节点的值。 所以所有的值都是字符串。 即使有数千个值被反/序列化,它的性能也很好。
例子:
const a = {
a: {
b: {
c: null,
d: true,
e: "hello"
}
}
}
const b = flatten(a)
console.log(b) /* =>
{
'/a/b/c': null,
'/a/b/d': true,
'/a/b/e': 'hello'
}
*/
Object.entries(b).forEach(([key, value]) => {
redis.set(key, JSON.stringify(value)) // or
redis.hset('my_hash', key, JSON.stringify(value)) /*
=> "/a/b/c" -> "null"
=> "/a/b/d" -> "true"
=> "/a/b/e" -> "\"hello\""
*/
})
如果您需要更多指导,请随时通过 Gitter 或通过我个人资料中的电子邮件与我联系。
@slidenerd另一种选择是使用ReJSON来存储您的 JSON 对象——它通常是一个更好的选择,手动序列化所有内容,并且可以处理空值和未定义。 它是 Redis 模块,因此您必须有一个支持它的版本 (4.0+) 并将该模块安装到服务器中。 这超出了这个 Node.js 模块(和这个问题)的范围,但它解决了这个问题。
items.push(JSON.stringify(object, (key, value) => {
if (value === null || value === undefined) {
return undefined
}
else {
return isNaN(parseFloat(value)) ? value : parseFloat(value)
}
}))
谢谢@stockholmux我想出了一个更好的解决方案,而不使用外部依赖,这个想法是在 JSON.stringify 方法中使用替换函数,它恰好是第二个参数
最有用的评论
我意识到 node-redis 不会对从 redis 检索到的字符串值进行任何数据类型转换。 我隐含地假设布尔值、数字等会自动转换为相应的 javascript 类型。 如果您认为这不在项目范围内,请关闭问题。
但是,自动转换会很好。 我只是花了大量时间调试由于错误值被检索为“false”并通过 javascript 的真值检查条件而引起的错误。