1

目前,当您在尝试检索视图后尝试执行查询时,您会发现视图不存在:

var result = _couchClient.GetView<etc>("DocumentName", "ViewNameThatDoesNotExist");
result.Count(); // This returns a service exception

在 Count 抛出异常后发现它不存在,所以目前我使用 try/catch 来确定是否存在异常。

有没有更优雅的解决方案,它不需要与执行查询一样多的资源?似乎没有类似的东西

result.exists()

或类似的东西。

4

3 回答 3

2

我创建了一个重载的 CouchbaseClient 来解决这个问题。它速度很快,而且效果很好。

编辑:我做了一个小改动,我没有使用 string.contains,我使用 Json 对象。

public class CouchbaseClientExtended : CouchbaseClient
{
    private string _bucket;
    private bool _isDevMode;
    private CouchbaseCluster _cluster;

    public CouchbaseClientExtended()
    {
        LoadBaseConfig("couchbase");
    }

    public CouchbaseClientExtended(CouchbaseClientConfiguration config) : base(config)
    {
        LoadBaseConfig(config);
    }

    public CouchbaseClientExtended(string sectionName) : base(sectionName)
    {
        LoadBaseConfig(sectionName);
    }

    public CouchbaseClientExtended(ICouchbaseServerPool pool, CouchbaseClientConfiguration config) : base(pool, config)
    {
        LoadBaseConfig(config);
    }

    public CouchbaseClientExtended(string bucketName, string bucketPassword) : base(bucketName, bucketPassword)
    {
        var config = new CouchbaseClientConfiguration
        {
            Bucket = bucketName,
            BucketPassword = bucketPassword
        };
        LoadBaseConfig(config);
        _bucket = bucketName;
    }

    public CouchbaseClientExtended(CouchbaseClientConfiguration config, string bucketName, string bucketPassword) : base(config, bucketName, bucketPassword)
    {
        LoadBaseConfig(config);
        _bucket = bucketName;
    }

    public CouchbaseClientExtended(string sectionName, string bucketName, string bucketPassword)
        : base(sectionName, bucketName, bucketPassword)
    {
        LoadBaseConfig(sectionName);
        _bucket = bucketName;
    }

    private void LoadBaseConfig(string sectionName)
    {
        var config = ConfigurationManager.GetSection(sectionName) as CouchbaseClientSection;
        if (config == null)
        {
            throw new NullReferenceException(
                "Couchbase configuration cannot be null. Add it to App.Config file or pass a custom one via parameter.");
        }
        _bucket = config.Servers.Bucket;
        _isDevMode = config.DocumentNameTransformer.Type == typeof (DevelopmentModeNameTransformer);
        _cluster = new CouchbaseCluster(config);
    }

    private void LoadBaseConfig(CouchbaseClientConfiguration config)
    {
        _bucket = config.Bucket;
        _isDevMode = config.DesignDocumentNameTransformer is DevelopmentModeNameTransformer;
        _cluster = new CouchbaseCluster(config);
    }

    public bool StoreJson<T>(StoreMode storeMode, string key, T value) where T : class
    {
        return Store(storeMode, key, JsonConvert.SerializeObject(value));
    }

    public T GetJson<T>(string key) where T : class
    {
        T obj = null;
        var json = Get<string>(key);
        if (json != null)
        {
            obj = JsonConvert.DeserializeObject<T>(json);
        }
        return obj;
    }

    public bool ViewExist(string designName, string viewName)
    {
        try
        {
            var doc = _cluster.RetrieveDesignDocument(_bucket, designName);
            if (!VerifyDesignDocumentContainsView(doc, viewName))
            {
                if (_isDevMode)
                {
                    var devDoc = _cluster.RetrieveDesignDocument(_bucket, "dev_" + designName);
                    return VerifyDesignDocumentContainsView(devDoc, viewName);
                }
                return false;
            }

            return true;
        }
        catch (WebException wex)
        {
            if (((HttpWebResponse)wex.Response).StatusCode == HttpStatusCode.NotFound)
            {
                return false;
            }
            throw;
        }
    }

    private bool VerifyDesignDocumentContainsView(string doc, string viewName)
    {
        if (string.IsNullOrEmpty(doc) || string.IsNullOrEmpty(viewName))
        {
            return false;
        }

        JToken token;
        JObject jObject = JsonConvert.DeserializeObject<JObject>(doc);
        jObject.TryGetValue("views", out token);
        if (token != null)
        {
            jObject = (JObject)token;
            return jObject.TryGetValue(viewName, out token);
        }
        return false;
    }
}

希望它对你有用:)

于 2013-01-14T21:41:39.500 回答
1

马特 - 感谢分享您的扩展方法!现在已经看到这个问题出现了几次,我正在为 1.2.1 客户端(将于 2013 年 2 月 5 日发布)提供支持。下面的答案在 1.2.0 中无效,但仅供将来参考。我还将它作为答案而不是评论包含在内,以更好地突出显示代码......

在 1.2.1 中,将有两种方法来检查不存在的视图。第一种是使用视图的新 CheckExists() 方法。此方法将查询设计文档并解析 JSON。类似于 Matt 的方法,但不使用 CouchbaseCluster API。

var view = client.GetView("designDoc", "viewName")

if (view.CheckExists())
{
  view.Count();
}

第二种方法是捕获异常,这是有意义的类型(不再是 InvalidOperationException)。这种方法的优点是少了一个 HTTP 查询。

var view = client.GetView("designDoc", "viewName")

try {
    view.Count();
} catch (ViewNotFoundException vnfe) { //extends ViewException
    ...
} catch (ViewException ve) { //bad params for example
   log.Error("Error {0}, Reason {1}", ve.Error, ve.Reason);
} catch (Exception e) {
   ...
}

Jira 请求位于http://www.couchbase.com/issues/browse/NCBC-165,代码正在审查中http://review.couchbase.org/#/c/24068/1

于 2013-01-18T21:12:35.820 回答
0

您可以尝试使用 Design REST API,不确定它是否更优雅,请参阅 http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-designdoc-api-retrieving.html

这种方法是一种非常通用的方法。

当您调用 getView() 方法时,我不是 .Net 专家,而是在 Java SDK 中,如果视图不退出,则会引发异常。也许您在.Net中有类似的方式

于 2012-11-24T12:05:27.300 回答