使用以特定字符串

时间:2015-11-06 16:41:43

标签: java couchbase

我试图从我的存储桶中删除其键以某个字符串开头的所有文档。

我的观点是:

private void createAndPublishCacheView()
{
 List<View> views = new ArrayList<View>();
 views.add(DefaultView.create("cache_view_by_key", "function (doc, meta) { emit(meta.id, null) }"));

 DesignDocument designDoc   = DesignDocument.create("cache_doc", views);
 this.cacheBucket.bucketManager().upsertDesignDocument(designDoc);
}

我的removeAll方法是(如果文档的键以&#39; callId&#39;开头,则删除文档):

public void removeAll(String callId) throws Exception
{
 final CountDownLatch latch = new CountDownLatch(1);
 ViewQuery query            = cacheView.startKeyDocId(callId);

 bucket.async()
    .query(query)
    .doOnNext(new Action1<AsyncViewResult>() 
              {
               @Override
               public void call(AsyncViewResult viewResult) 
               {
                if (!viewResult.success()) throw new RuntimeException();
               }
              }
             )
    .flatMap(new Func1<AsyncViewResult, Observable<AsyncViewRow>>() 
             {
              @Override
              public Observable<AsyncViewRow> call(AsyncViewResult viewResult) 
              {
               return viewResult.rows();
              }
             }
            )
    .subscribe(new Subscriber<AsyncViewRow>() 
               {
                @Override
                public void onCompleted() { latch.countDown(); }

                @Override
                public void onError(Throwable t) { throw new RuntimeException(t.getMessage()); }

                @Override
                public void onNext(AsyncViewRow viewRow) 
                { 
                 System.out.println("viewRow.id() = " + viewRow.id());
                 bucket.remove(viewRow.id());
                }
               }
              );

 latch.await();
 }

我是Observables的初学者。如果onNext方法是:

  public void onNext(AsyncViewRow viewRow) 
                { 
                 System.out.println("viewRow.id() = " + viewRow.id());
                 bucket.remove(viewRow.id());
                }

然后只有几个文件打印在控制台上并被删除,我收到了:

java.lang.RuntimeException: java.util.concurrent.TimeoutException
at com.couchbase.client.java.util.Blocking.blockForSingle(Blocking.java:75)
at com.couchbase.client.java.CouchbaseBucket.remove(CouchbaseBucket.java:486)
at com.couchbase.client.java.CouchbaseBucket.remove(CouchbaseBucket.java:466)
at com.ventusproxy.tests.couchbase.TestCB$3.onNext(TestCB.java:167)
at com.ventusproxy.tests.couchbase.TestCB$3.onNext(TestCB.java:1)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:130)

如果onNext方法是:

  public void onNext(AsyncViewRow viewRow) 
                { 
                 System.out.println("viewRow.id() = " + viewRow.id());
                 bucket.async().remove(viewRow.id());
                }

然后所有文件都打印在控制台上,但不会删除。

任何人都可以帮助我吗?

此外,我不确定这是否是删除大量文档的最有效方式。

谢谢,

琼。

1 个答案:

答案 0 :(得分:0)

您尝试做的事情有一些问题:

  1. startKeyDocId方法实际上并没有按照您的想法执行。使用 startKey(callId)
  2. 仅指定开始键将返回大于的所有结果 参数,不仅是以该确切键开头的结果。视图 查询按字典顺序按升序比较键,因此您将获得大于callId的所有字符串。你应该指定两者 查询中的开始和结束键以及包含端,以正确限制它。所以cacheView.startKey(callId).endKey(calldId).inclusiveEnd(true)(从内存中输入,语法可能略有偏差。)
  3. 您尝试一次检索所有匹配的密钥。如果有 很多结果,查询将超时只是因为它将采取 太长时间无法返回所有结果。如果你期望很多结果(比如说 超过1000)你应该使用分页来检索和处理它们 块。以下是如何在RxJava中使用Observable实现分页的一个很好的示例:How to handle paging with RxJava?
  4. 您异步调用View查询但使用阻塞删除调用。您应该flatMap进入bucket.async().remove(row.id()) - 而不是订阅异步查询调用的结果 - 然后您可以订阅所有异步删除调用的结果,添加一些重试和错误处理逻辑等请看这里有关实现重试和错误处理的信息:http://developer.couchbase.com/documentation/server/4.0/sdks/java-2.2/observables.html#story-h2-10(特别滚动到retryWhen示例。)
  5. 最后,如果您使用的是Couchbase 4.0,则可以使用以下N1QL查询替换整个内容:DELETE FROM bucket WHERE META(bucket).id like 'ABC%';