使用rethinkdb数据资源管理器
r.db('exports').table('requests')
取
{
"options": {
"params": {
"foo": "bof"
"sort": "desc",
"page": 6
}
} ,
"url": "https://url1.tld/"
}
{
"options": {
"auth": {
"type": "basic" ,
"pass": "dnkykngcntry1" ,
"user": "diddy"
} ,
"params": {
"foo": "bar"
"sort": "asc",
"page": 3
}
} ,
"url": "https://url2.test/"
}
...
现在我想这样做
r.db('exports').table('responses').insert(
r.db('exports').table('requests').map(req => ({
requestId: req('id'),
requestedAt: r.now(),
response: r.http(req('url'), req('options'))
}))
)
出现此错误:
e: Expected 1 argument (not including options) but found 2.
如果我使用其中一个request
文档中的值调用r.http
函数,一切正常
// http command syntax
// r.http(url[, options]) → value
// r.http(url[, options]) → stream
r.http("https://url1.tld/", {
"params": {
"foo": "bof"
"sort": "desc",
"page": 6
}
})
// <response text>
为什么它不适用于循环中的req('url')
和req('options')
?
答案 0 :(得分:1)
我不是RethinkDB专家,但我可能会对问题做一个简单的浅析/解决(假设你正在使用JavaScript)。
为什么它不能在循环中与
req('url')
和req('options')
一起使用?
我认为这不是一个与循环相关的问题,而且RethinkDB处理ReQL表达式和可能的参数(如果将错误消息考虑在内)的可能性更大。
req('url')
和req('options')
都是ReQL表达式,可以使用r.expr(...)
手动实例化。
请考虑以下与您的问题相关的代码:
// These two are your req('url') and req('options') equivalents respectively
const url = r.expr('https://postman-echo.com/get');
const options = r.expr({ params: { foo: 1, bar: 2 } });
// ...
r.http(url, options);
e:预期1个参数(不包括选项)但找到2。
好的,让我们尝试使用简单的options
在没有r.http(url)
参数的情况下运行它,这就是它的结果:
{
"args": { },
"headers": {
"accept": "*/*",
"accept-encoding": "deflate, gzip",
"host": "postman-echo.com",
"user-agent": "RethinkDB/2.3.2-windows-beta-472-ga2117b",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
} ,
"url": "https://postman-echo.com/get"
}
我相信r.expr(...)
- 实例化的ReQL值在is-this-options检测时与options
发生冲突(可能是由于undefined
导致的相同行为) 。
您所要做的就是将文档属性包装在原始JavaScript对象中,因为RethinkDB似乎与嵌套属性完美配合。
r.http(url, rebuildOptions(options));
由于rebuildOptions
API限制,r.http()
可以作为相当有限的功能实现,例如:
const rebuildOptions = options => ({
method: options('method').default('GET'), // default GET is fine for method
// auth: don't know how to deal with auth - we cannot assign undefined to the property and cannot provide the default auth too
params: options('params').default({}), // default {} is fine for params
header: options('header').default({}), // the headers will be merged in the final request
// data: don't know how to deal with data too - we can analyze options('method'), but cannot assign a good default value
});
肮脏和虚弱。 我还可以建议更多&#34; hackish&#34;我在检查ReQL值结构时发现了更通用的实现:
// This looks to work with any ReQL values
const unexpr = expr => Object.assign({}, expr.optargs);
r.http(url, unexpr(options));
现在两个实现都可以返回:
{
"args": {
"bar": "2",
"foo": "1"
} ,
"headers": {
"accept": "*/*",
"accept-encoding": "deflate, gzip",
"host": "postman-echo.com",
"user-agent": "RethinkDB/2.3.2-windows-beta-472-ga2117b",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
} ,
"url": "https://postman-echo.com/get?bar=2&foo=1"
}
它看起来像一个设计缺陷(r.expr()
没有它的&#34; unwrapper&#34;对应物,如果RethinkDB曾经需要它)或一个可选的参数检测bug,并且可能值得提交给{ {3}}至少要获得RethinkDB团队的反馈意见。
答案 1 :(得分:1)
请记住,您正在构建一个要发送到服务器的查询,上面描述的函数rebuildOptions
构造了一个表达式来自&#34;选项&#34;表达。这可能会导致服务器在三个不同的地方重新评估options
表达式。 (并且在实践中,这确实会发生。)对于查询构造辅助函数,最好使用r.do
构造查询以避免重新评估参数表达式,如果表达式在较大的表达式中使用多次围绕它建立的表达。
const rebuildOptions = options => options.do(x => ({
method: x('method').default('GET'),
params: x('params').default({}),
header: x('header').default({}),
}));
正如我在Github问题中提到的那样,这是一个有意的设计决定。必须提供函数的可选参数&#34;静态地,&#34;不同语言的不同客户端驱动程序可能不代表使用单个字典的可选参数。