var offset = 1;
var limit = 500;
var list = new Promise(function (resolve, reject) {
rets.getAutoLogoutClient(config.clientSettings, (client) => {
var results = client.search.query(SearchType, Class, Query, {
limit: limit,
offset: offset
});
resolve(results);
});
});
var source = Rx.Observable.fromPromise(list);
source.subscribe(results => console.log(results.count));
我正在使用RETS做房地产网站。
我正在尝试进行的查询仅限于RETS服务器,在循环中运行此操作会增加我的偏移量,直到我拥有所有数据。在运行查询并找到计数值之前,我不知道计数是什么。
我试过使用扩展,但我不知道它究竟是如何工作的。试图做这些多种方式,甚至使用旧的时尚循环,虽然没有使用.then方法。所以我已经转向RXJS,因为我在Angular 4中使用它。
这是在快递中完成的。我需要最终运行corn作业来获取更新的属性,但我的问题是获取所有数据并且每次增加偏移量,如果计数高于我的偏移量。因此,例如,运行一个偏移量为1且限制为500的查询。总计这里是1690.所以接下来绕过我的偏移量将是:
offset += limit
获得数据后,我需要将其保存到MongoDB。我已经成功做到了。它只是找到一种获取所有数据的方法,而无需手动设置我的偏移量。
请注意,服务器限制为2500,是的,我可以一次性获取所有这些,但也有其他数据,例如媒体,可能超过2500.
有什么建议吗?
答案 0 :(得分:0)
这实际上是RxJS的一个相当常见的用例,因为有很多分页数据源,或者在您可以同时请求的内容中限制的来源。
我的两分钱
在我看来,expand
可能是最好的操作符,因为您要对未知数据源进行分页,并且至少需要一个查询才能确定最终计数。如果你知道要查询多少数据,那么使用mergeScan
之类的东西就更容易了,但我离题了。
提议的解决方案
这可能需要花费一些力气来包围你,所以我尽可能地添加了注释来分解这一切是如何工作的。 注意我实际上没有测试过这个,所以请原谅我任何语法错误。
// Your constant limit for any one query
const limit = 500;
// RxJS helper method that wraps the async call into an Observable
// I am basing this on what I saw of your sample which leads me to believe
// that this should work.
const clientish = Rx.Observable.bindCallback(rets.getAutoLogoutClient);
// A method wrapper around your query call that wraps the resulting promise
// into a defer.
const queryish = (client, params) =>
// Note the use of defer here is deliberate, since the query returns
// a promise that will begin executing immediately, this prevents that behavior
// And forces execution on subscription.
Rx.Observable.defer(() => client.search.query(SearchType, Class, Query, params));
// This does the actual expansion function
// Note this is a higher order function because the client and the parameters
// are available at different times
const expander = (client) => ({limit, count}) =>
// Invoke the query method
queryish(client, {limit, count})
// Remap the results, update offset and count and forward the whole
// package down stream
.map(results => ({
limit,
count: results.count,
offset: offset + limit,
results
}));
// Start the stream by constructing the client
clientish(config.clientSettings)
.switchMap(client =>
// This are the arguments for the initial call
Rx.Observable.of({limit, offset: 0})
// Call the expander function with the client
// The second argument is the max concurrency, you can change that if needed
.expand(expander(client), 1)
// Expand will keep recursing unless you tell it to stop
// This will halt the execution once offset exceeds count, i.e. you have
// all the data
.takeWhile(({count, offset}) => offset < count)
// Further downstream you only care about the results
// So extract them from the message body and only forward them
.pluck('results')
)
.subscribe(results => /*Do stuff with results*/);
答案 1 :(得分:0)
const retsConnect = Rx.Observable.create(function(observer) {
rets.getAutoLogoutClient(config.clientSettings, client => {
return searchQuery(client, 500, 1, observer);
});
});
function searchQuery(client, limit, offset, observer) {
let currentOffset = offset === undefined || offset === 0 ? 1 : offset;
return client.search.query(SearchType, Class, Query, {limit: limit, offset: currentOffset})
.then(results => {
offset += limit;
observer.next(results.maxRowsExceeded);
if (results.maxRowsExceeded) {
console.log(offset);
return searchQuery(client, limit, offset, observer);
} else {
console.log('Completed');
observer.complete();
}
});
}
retsConnect.subscribe(val => console.log(val));
所以这是我在这里尝试过的地方。我还在调整这个。所以我要做的是更多地打破searchQuery。不知道我是否应该在那里传递observer.next,所以我要弄清楚在哪里映射并重新安装返回searchQuery。我不确定takeUntil会采取真或假的方式。我只需要将这些数据保存到mongodb中。所以我想我可以这样离开它并将我的保存方法放在那里,但我仍然想知道这一点。
注意:当还有更多数据时,results.maxRowsExceeded返回true。因此,一旦maxRows返回false,它将停止并且所有数据都已被提取。