2017-10-15 58 views
0

使用rethinkdb数据探索如何在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. 

如果我称之为r.http函数值从request文件之一,一切工作正常

// 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')在循环工作呢?

回答

1

我不是RethinkDB专家,但我可能会对此问题做一个简单的浅析浅析/修复(假设您正在使用JavaScript)。

Why doesn't it work with req('url') and req('options') in the loop then?

我不认为这是一个循环有关的问题,它更可能与ReQL表情和可能可选参数的方式RethinkDB交易的(如果以错误信息考虑在内)。 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: Expected 1 argument (not including options) but found 2.

好吧,让我们尽量不使用简单r.http(url)options参数运行它,这就是它得到:

{ 
    "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(...) -instantiated ReQL值与options在检测到is-this-option时可能发生冲突(可能是由于t o与undefined相同的行为)。 您只需将文档属性封装在原始JavaScript对象中,因为RethinkDB似乎可以与嵌套属性完美协作。

r.http(url, rebuildOptions(options)); 

其中rebuildOptions可以被实施为相当有限的功能由于r.http() API限制,例如:

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 
}); 

脏和弱。 我也可以提出一个更“hackish的”和更通用的实现,我在考察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()没有它的“unwrapper”副本,如果RethinkDB有需要的话)或可选参数检测错误,并且可能值得提交到RethinkDB issue tracker至少得到Re thinkDB团队反馈。

+0

我希望我可以表达这个答案对我来说有多快乐 - 看起来我们在尝试解决这个问题时采用了相同的路径 - 我使用r.http(req('url'),{auth:req ('options')('auth'),params:req('options')('params')})' - 这是您的'rebuildOptions'解决方案的更糟糕的版本 - 我有相同的预感wrt“可选参数检测错误“和”r.expr“的设计不完美......因此,您的'unexpr'解决方案*非常吸引人;也很独特;一个非常优雅的解决方法 - 感谢堆^ _^ – naomik

+0

我[在这里提交了一个问题](https://github.com/rethinkdb/rethinkdb/issues/6523) - 也许你想贡献你的帖子到github线程呢?我将把这个问题标记为答案。 – naomik

+0

SamHughes告诉我,'unexpr'只能在这里工作,因为这个对象是用'R.expr'构造的;在真正的查询中,这不会**工作 - 'rebuildOptions'方法是这样做的正确方法,但是Sam还会使用'.do'来优化其性能。看到他的回答详情 – naomik

1

请记住,您正在构建一个查询以发送到服务器,并且上述函数rebuildOptions构建了一个表达式“options”表达式。这可能会导致服务器在三个不同的地方重新评估options表达式。 (实际上,这确实会发生。)对于查询构造助手函数,使用r.do构造查询以避免重新评估参数表达式是一个好主意,如果表达式在围绕它构建的较大表达式中多次使用。

const rebuildOptions = options => options.do(x => ({ 
    method: x('method').default('GET'), 
    params: x('params').default({}), 
    header: x('header').default({}), 
})); 

正如我在Github的问题中提到的那样,这是一个有意的设计决定。函数的可选参数必须“静态”提供,而不同语言的不同客户端驱动程序可能不会使用单个字典表示可选参数。

+0

好吧,这有助于我更好地理解;感谢Sam的一切 – naomik

相关问题