Skip to content
Browse files

NCBC-47: Add support for spatial view queries

Change-Id: I339bc3ea0c4a1ff4bf7c782db729a2009a5ca61f
Reviewed-on: http://review.couchbase.org/22420
Reviewed-by: Matt Ingenthron <matt@couchbase.com>
Reviewed-by: Volker Mische <volker.mische@gmail.com>
Tested-by: John C. Zablocki <john@couchbase.com>
  • Loading branch information...
1 parent ffaba6e commit 48cc56fb05dd50d01134da057091710ff02f3410 @johnzablocki johnzablocki committed with John C. Zablocki Nov 8, 2012
View
2 src/Couchbase.Tests/Couchbase.Tests.csproj
@@ -51,6 +51,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ConfigHelperTests.cs" />
+ <Compile Include="CouchbaseClientSpatialViewTests.cs" />
+ <Compile Include="HelperTests\DocHelperTests.cs" />
<Compile Include="HttpClientConfigTests.cs" />
<Compile Include="CouchbaseAuthenticatedViewTests.cs" />
<Compile Include="CouchbaseClientGenericViewTests.cs" />
View
99 src/Couchbase.Tests/CouchbaseClientSpatialViewTests.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Couchbase.Extensions;
+
+namespace Couchbase.Tests
+{
+ [TestFixture]
+ public class CouchbaseClientSpatialViewTests : CouchbaseClientViewTestsBase
+ {
+ [Test]
+ public void When_Querying_Spatial_View_Results_Are_Returned()
+ {
+ var view = _Client.GetSpatialView("cities", "by_location");
+ foreach (var item in view)
+ {
+ Assert.That(item.Id, Is.Not.Null, "Item Id was null");
+ Assert.That(item.BoundingBox, Is.Not.Null, "Bounding box was null");
+ Assert.That(item.BoundingBox.Length, Is.GreaterThan(0), "Bounding length box was empty");
+ Assert.That(item.Geometry.Type, Is.StringMatching("Point"), "Type was not place");
+ Assert.That(item.Geometry.Coordinates, Is.InstanceOf<float[]>(), "Coordinates were missing");
+ }
+
+ Assert.That(view.Count(), Is.GreaterThan(0), "View count was 0");
+ }
+
+ [Test]
+ public void When_Querying_Spatial_View_With_Generics_And_Should_Lookup_Doc_By_Id_Is_True_Results_Are_Returned()
+ {
+ var view = _Client.GetSpatialView<City>("cities", "by_location", true);
+ foreach (var item in view)
+ {
+ Assert.That(item.Id, Is.Not.Null, "Id was null");
+ Assert.That(item.Name, Is.Not.Null, "Name was null");
+ Assert.That(item.State, Is.Not.Null, "State was null");
+ Assert.That(item.Type, Is.StringMatching("city"), "Type was not city");
+ }
+
+ Assert.That(view.Count(), Is.GreaterThan(0), "View count was 0");
+ }
+
+ [Test]
+ public void When_Querying_Spatial_View_With_Generics_And_Should_Lookup_Doc_By_Id_Is_False_Results_Are_Returned()
+ {
+ var view = _Client.GetSpatialView<CityProjection>("cities", "by_location_with_city_name", false);
+ foreach (var item in view)
+ {
+ Assert.That(item.CityState, Is.Not.Null);
+ }
+
+ Assert.That(view.Count(), Is.GreaterThan(0), "View count was 0");
+ }
+
+ [Test]
+ public void When_Querying_Spatial_View_With_Limit_Rows_Are_Limited()
+ {
+ var view = _Client.GetSpatialView("cities", "by_location").Limit(2);
+ Assert.That(view.Count(), Is.EqualTo(2), "View count was not 2");
+ }
+
+ [Test]
+ public void When_Querying_Spatial_View_With_Bounding_Box_Rows_Are_Limited()
+ {
+ var hasAtLeastOneRecord = false;
+ var view = _Client.GetSpatialView("cities", "by_location").BoundingBox(-73.789673f, 41.093704f, -71.592407f, 42.079742f); //bbox around Connecticut
+ foreach (var item in view)
+ {
+ hasAtLeastOneRecord = true;
+ var doc = _Client.GetJson<City>(item.Id);
+ Assert.That(doc.State, Is.StringMatching("CT"), "State was " + doc.State + " not CT");
+ }
+
+ Assert.That(hasAtLeastOneRecord, Is.True, "No records found");
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
44 src/Couchbase.Tests/Data/CityDocs.json
@@ -1,22 +1,22 @@
-{ "name" : "Hartford", "state" : "CT", "type" : "city" }
-{ "name" : "Bridgeport", "state" : "CT", "type" : "city" }
-{ "name" : "Stamford", "state" : "CT", "type" : "city" }
-{ "name" : "New Haven", "state" : "CT", "type" : "city" }
-{ "name" : "New London", "state" : "CT", "type" : "city" }
-{ "name" : "Norwalk", "state" : "CT", "type" : "city" }
-{ "name" : "Boston", "state" : "MA", "type" : "city" }
-{ "name" : "Cambridge", "state" : "MA", "type" : "city" }
-{ "name" : "Somerville", "state" : "MA", "type" : "city" }
-{ "name" : "Springfield", "state" : "MA", "type" : "city" }
-{ "name" : "Worcester", "state" : "MA", "type" : "city" }
-{ "name" : "Portsmouth", "state" : "NH", "type" : "city" }
-{ "name" : "Concord", "state" : "NH", "type" : "city" }
-{ "name" : "Manchester", "state" : "NH", "type" : "city" }
-{ "name" : "Burlington", "state" : "VT", "type" : "city" }
-{ "name" : "Montpelier", "state" : "VT", "type" : "city" }
-{ "name" : "Newport", "state" : "VT", "type" : "city" }
-{ "name" : "Providence", "state" : "RI", "type" : "city" }
-{ "name" : "Warwick", "state" : "RI", "type" : "city" }
-{ "name" : "Newport", "state" : "RI", "type" : "city" }
-{ "name" : "Bangor", "state" : "ME", "type" : "city" }
-{ "name" : "Portland", "state" : "ME", "type" : "city" }
+{ "name" : "Hartford", "state" : "CT", "type" : "city", "loc" : [-72.67408, 41.763309] }
+{ "name" : "Bridgeport", "state" : "CT", "type" : "city", "loc" : [-73.191269, 41.181881] }
+{ "name" : "Stamford", "state" : "CT", "type" : "city", "loc" : [-73.542229, 41.051819] }
+{ "name" : "New Haven", "state" : "CT", "type" : "city", "loc" : [-72.92498, 41.307129] }
+{ "name" : "New London", "state" : "CT", "type" : "city", "loc" : [-72.096474, 41.356441] }
+{ "name" : "Norwalk", "state" : "CT", "type" : "city", "loc" : [-73.407654, 41.113659] }
+{ "name" : "Boston", "state" : "MA", "type" : "city", "loc" : [-71.056702, 42.358631] }
+{ "name" : "Cambridge", "state" : "MA", "type" : "city", "loc" : [-71.10601, 42.366791] }
+{ "name" : "Somerville", "state" : "MA", "type" : "city", "loc" : [-71.098259, 42.386681] }
+{ "name" : "Springfield", "state" : "MA", "type" : "city", "loc" : [-72.589287, 42.10125] }
+{ "name" : "Worcester", "state" : "MA", "type" : "city", "loc" : [-71.802193, 42.263409] }
+{ "name" : "Portsmouth", "state" : "NH", "type" : "city", "loc" : [-70.772118, 43.070621] }
+{ "name" : "Concord", "state" : "NH", "type" : "city", "loc" : [-71.536598, 43.207249] }
+{ "name" : "Manchester", "state" : "NH", "type" : "city", "loc" : [-71.463089, 42.991169] }
+{ "name" : "Burlington", "state" : "VT", "type" : "city", "loc" : [-73.213226, 44.475922] }
+{ "name" : "Montpelier", "state" : "VT", "type" : "city", "loc" : [-72.576263, 44.260288] }
+{ "name" : "Newport", "state" : "VT", "type" : "city", "loc" : [-72.210617, 44.935341] }
+{ "name" : "Providence", "state" : "RI", "type" : "city", "loc" : [-71.411987, 41.823872] }
+{ "name" : "Warwick", "state" : "RI", "type" : "city", "loc" : [-71.461678, 41.698589] }
+{ "name" : "Newport", "state" : "RI", "type" : "city", "loc" : [-71.311333, 41.492161] }
+{ "name" : "Bangor", "state" : "ME", "type" : "city", "loc" : [-68.770767, 44.801708] }
+{ "name" : "Portland", "state" : "ME", "type" : "city", "loc" : [-70.256653, 43.659142] }
View
6 src/Couchbase.Tests/Data/CityViews.json
@@ -13,5 +13,9 @@
"map": "function (doc) { if (doc.type == \"city\") { emit(doc.state, doc.name); } }",
"reduce": "_count"
}
- }
+ },
+ "spatial" : {
+ "by_location" : "function (doc, meta) { if (doc.type == \"city\") { emit({ \"type\": \"Point\", \"coordinates\": doc.loc}, null); } }",
+ "by_location_with_city_name" : "function (doc, meta) { if (doc.type == \"city\") { emit({ \"type\": \"Point\", \"coordinates\": doc.loc}, { \"cityState\" : doc.name + \",\" + doc.state }); } }"
+ }
}
View
45 src/Couchbase.Tests/HelperTests/DocHelperTests.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Couchbase.Helpers;
+using Newtonsoft.Json;
+
+namespace Couchbase.Tests.HelperTests
+{
+ [TestFixture]
+ public class DocHelperTests
+ {
+ [Test]
+ public void When_Inserting_Id_Into_Doc_Json_String_Is_Valid_And_Contains_Id()
+ {
+ var json = "{ \"message\" : \"Test\" }";
+ var jsonWithId = DocHelper.InsertId(json, "8675309");
+
+ Assert.That(jsonWithId, Is.StringContaining("\"_id\":\"8675309\""));
+ Assert.That(JsonConvert.DeserializeObject(jsonWithId), Is.Not.Null);
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
14 src/Couchbase/Couchbase.csproj
@@ -51,6 +51,7 @@
<HintPath>..\packages\Newtonsoft.Json.4.5.1\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
+ <Reference Include="System.Configuration" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -71,8 +72,15 @@
<ItemGroup>
<Compile Include="Configuration\HttpClientElement.cs" />
<Compile Include="Configuration\IHttpClientConfiguration.cs" />
+ <Compile Include="CouchbaseSpatialView`1.cs" />
+ <Compile Include="CouchbaseSpatialView.cs" />
+ <Compile Include="CouchbaseSpatialViewBase.cs" />
+ <Compile Include="CouchbaseViewHandler.cs" />
<Compile Include="Extensions\CouchbaseClientExtensions.cs" />
+ <Compile Include="Helpers\DocHelper.cs" />
<Compile Include="Helpers\JsonHelper.cs" />
+ <Compile Include="ISpatialView`1.cs" />
+ <Compile Include="ISpatialViewRow.cs" />
<Compile Include="Management\Bucket.cs" />
<Compile Include="BucketConfigListener.cs" />
<Compile Include="BucketConfigSettings.cs" />
@@ -150,7 +158,10 @@
<Compile Include="Results\IObserveOperationResult.cs" />
<Compile Include="Results\ObserveOperationResult.cs" />
<Compile Include="Settings\ObserveSettings.cs" />
+ <Compile Include="SpatialViewGeometry.cs" />
+ <Compile Include="SpatialViewRow.cs" />
<Compile Include="VBucketAwareOperationFactory.cs" />
+ <Compile Include="ViewParamsBuilder.cs" />
<Compile Include="WebClientWithTimeout.cs">
<SubType>Component</SubType>
</Compile>
@@ -168,6 +179,9 @@
<Name>Enyim.Caching</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Geo\" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<GitTagMatch>mb*</GitTagMatch>
View
12 src/Couchbase/CouchbaseClient.cs
@@ -715,6 +715,18 @@ public IView<T> GetView<T>(string designName, string viewName, bool shouldLookup
return new CouchbaseView<T>(this, this, designName, viewName, shouldLookupDocById);
}
+ public ISpatialView<ISpatialViewRow> GetSpatialView(string designName, string viewName)
+ {
+ getViewSetup(ref designName, ref viewName);
+ return new CouchbaseSpatialView(this, this, designName, viewName);
+ }
+
+ public ISpatialView<T> GetSpatialView<T>(string designName, string viewName, bool shouldLookupDocById = false)
+ {
+ getViewSetup(ref designName, ref viewName);
+ return new CouchbaseSpatialView<T>(this, this, designName, viewName, shouldLookupDocById);
+ }
+
public IDictionary<string, object> Get(IView view)
{
var keys = view.Select(row => row.ItemId);
View
41 src/Couchbase/CouchbaseSpatialView.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Couchbase
+{
+ internal class CouchbaseSpatialView : CouchbaseSpatialViewBase<ISpatialViewRow>
+ {
+ internal CouchbaseSpatialView(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName)
+ :base(client, clientLocator, designDocument, indexName) {}
+
+ public override IEnumerator<ISpatialViewRow> GetEnumerator()
+ {
+ return ViewHandler.TransformResults<ISpatialViewRow>(
+ jr => JsonConvert.DeserializeObject<SpatialViewRow>(Json.ParseRaw(jr)), BuildParams());
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
104 src/Couchbase/CouchbaseSpatialViewBase.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+using System.Collections;
+
+namespace Couchbase
+{
+ internal abstract class CouchbaseSpatialViewBase<T> : ISpatialView<T>
+ {
+ protected readonly CouchbaseViewHandler ViewHandler;
+
+ private float[] _boundingBox;
+ private StaleMode? _stale;
+ private int _limit;
+ private int _skip;
+
+ internal CouchbaseSpatialViewBase(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName)
+ {
+ ViewHandler = new CouchbaseViewHandler(client, clientLocator, designDocument, indexName, "_spatial");
+ }
+
+ public ISpatialView<T> BoundingBox(float lowerLeftLong, float lowerLeftLat, float upperRightLong, float upperRightLat)
+ {
+ _boundingBox = new float[] { lowerLeftLong, lowerLeftLat, upperRightLong, upperRightLat };
+ return this;
+ }
+
+ public ISpatialView<T> Limit(int limit)
+ {
+ _limit = limit;
+ return this;
+ }
+
+ public ISpatialView<T> Skip(int skip)
+ {
+ _skip = skip;
+ return this;
+ }
+
+ public ISpatialView<T> Stale(StaleMode stale)
+ {
+ _stale = stale;
+ return this;
+ }
+
+ protected IDictionary<string, string> BuildParams()
+ {
+ var viewParamsBuilder = new ViewParamsBuilder();
+ if (_boundingBox != null)
+ {
+ if (_boundingBox.Length != 4)
+ {
+ throw new ArgumentException("4 coordinates must be supplied for bounding box");
+ }
+
+ viewParamsBuilder.AddParam("bbox", string.Join(",", _boundingBox));
+ }
+
+ viewParamsBuilder.AddGreaterThanOneParam("limit", _limit);
+ viewParamsBuilder.AddOptionalParam("skip", _skip);
+ viewParamsBuilder.AddStaleParam(_stale);
+
+ return viewParamsBuilder.Build();
+ }
+
+ #region IEnumerable<T> Members
+
+ public abstract IEnumerator<T> GetEnumerator();
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
60 src/Couchbase/CouchbaseSpatialView`1.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+using Couchbase.Helpers;
+
+namespace Couchbase
+{
+ internal class CouchbaseSpatialView<T> : CouchbaseSpatialViewBase<T>
+ {
+ private readonly bool _shouldLookupDocById;
+
+ internal CouchbaseSpatialView(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName, bool shouldLookUpDocById = false)
+ : base(client, clientLocator, designDocument, indexName)
+ {
+ _shouldLookupDocById = shouldLookUpDocById;
+ }
+
+ public override IEnumerator<T> GetEnumerator()
+ {
+ return ViewHandler.TransformResults<T>((jr) =>
+ {
+ if (_shouldLookupDocById)
+ {
+ var key = Json.ParseValue(jr, "id") as string;
+ var json = ViewHandler.Client.Get<string>(key);
+ var jsonWithId = DocHelper.InsertId(json, key);//_id is omitted from the Json return by Get
+ return JsonConvert.DeserializeObject<T>(jsonWithId);
+ }
+ else
+ {
+ var jObject = Json.ParseValue(jr, "value");
+ return JsonConvert.DeserializeObject<T>(jObject);
+ }
+ }, BuildParams());
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
4 src/Couchbase/CouchbaseView.cs
@@ -18,7 +18,7 @@ namespace Couchbase
/// </summary>
internal class CouchbaseView : CouchbaseViewBase<IViewRow>
{
- internal CouchbaseView(IMemcachedClient client, IHttpClientLocator clientLocator, string designDocument, string indexName)
+ internal CouchbaseView(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName)
: base(client, clientLocator, designDocument, indexName) { }
protected CouchbaseView(CouchbaseViewBase<IViewRow> original)
@@ -69,7 +69,7 @@ object[] IViewRow.ViewKey
object IViewRow.GetItem()
{
- return this.owner.client.Get(this.id);
+ return this.owner.ViewHandler.Client.Get(this.id);
}
IDictionary<string, object> IViewRow.Info
View
194 src/Couchbase/CouchbaseViewBase.cs
@@ -10,18 +10,11 @@
namespace Couchbase {
- public enum StaleMode { AllowStale, UpdateAfter, False }
-
- public enum OnErrorMode { Continue, Stop }
-
internal abstract class CouchbaseViewBase<T> : IView<T> {
protected static readonly Enyim.Caching.ILog log = Enyim.Caching.LogManager.GetLogger(typeof(CouchbaseView));
- protected readonly IMemcachedClient client;
- protected readonly IHttpClientLocator clientLocator;
- protected readonly string designDocument;
- protected readonly string indexName;
+ protected readonly CouchbaseViewHandler ViewHandler;
protected string endKey;
protected string startKey;
@@ -42,19 +35,16 @@ internal abstract class CouchbaseViewBase<T> : IView<T> {
protected bool? group;
protected int? groupAt;
- public int TotalRows { get; set; }
+ public int TotalRows {
+ get { return ViewHandler.TotalRows; }
+ }
- internal CouchbaseViewBase(IMemcachedClient client, IHttpClientLocator clientLocator, string designDocument, string indexName) {
- this.client = client;
- this.clientLocator = clientLocator;
- this.designDocument = designDocument;
- this.indexName = indexName;
+ internal CouchbaseViewBase(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName) {
+ this.ViewHandler = new CouchbaseViewHandler(client, clientLocator, designDocument, indexName);
}
protected CouchbaseViewBase(CouchbaseViewBase<T> original) {
- this.clientLocator = original.clientLocator;
- this.designDocument = original.designDocument;
- this.indexName = original.indexName;
+ this.ViewHandler = original.ViewHandler;
this.startKey = original.startKey;
this.endKey = original.endKey;
@@ -73,167 +63,33 @@ internal abstract class CouchbaseViewBase<T> : IView<T> {
this.groupAt = original.groupAt;
}
- protected bool MoveToArray(JsonReader reader, int depth, string name) {
- while (reader.Read()) {
- if (reader.TokenType == Newtonsoft.Json.JsonToken.PropertyName
- && reader.Depth == depth
- && ((string)reader.Value) == name) {
- if (!reader.Read()
- || (reader.TokenType != Newtonsoft.Json.JsonToken.StartArray
- && reader.TokenType != Newtonsoft.Json.JsonToken.Null))
- throw new InvalidOperationException("Expecting array named '" + name + "'!");
-
- // we skip the deserialization if the array is null
- return reader.TokenType == Newtonsoft.Json.JsonToken.StartArray;
- }
- }
-
- return false;
- }
-
protected IEnumerator<T> TransformResults<T>(Func<JsonReader, T> rowTransformer) {
- var response = GetResponse();
- Debug.Assert(response != null);
-
- using (var sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8, true))
- using (var jsonReader = new JsonTextReader(sr)) {
-
- while (jsonReader.Read())
- {
- if (jsonReader.TokenType == JsonToken.PropertyName && jsonReader.Depth == 1)
- {
- if (jsonReader.Value as string == "total_rows" && jsonReader.Read())
- {
- TotalRows = Convert.ToInt32(jsonReader.Value);
- }
- else if (jsonReader.Value as string == "rows" && jsonReader.Read())
- {
- // position the reader on the first "rows" field which contains the actual resultset
- // this way we do not have to deserialize the whole response twice
- // read until the end of the rows array
- while (jsonReader.Read() && jsonReader.TokenType != Newtonsoft.Json.JsonToken.EndArray)
- {
- var row = rowTransformer(jsonReader);
- yield return row;
- }
-
- if (MoveToArray(jsonReader, 1, "errors"))
- {
- var errors = Json.Parse(jsonReader);
- var formatted = String.Join("\n", FormatErrors(errors as object[]).ToArray());
- if (String.IsNullOrEmpty(formatted)) formatted = "<unknown>";
-
- throw new InvalidOperationException("Cannot read view: " + formatted);
- }
- }
- }
- }
- }
- }
-
- protected static IEnumerable<string> FormatErrors(object[] list) {
- if (list == null || list.Length == 0)
- yield break;
-
- foreach (IDictionary<string, object> error in list) {
- object reason;
- object from;
-
- if (!error.TryGetValue("from", out from)) continue;
- if (!error.TryGetValue("reason", out reason)) continue;
-
- yield return from + ": " + reason;
- }
- }
- /// <summary>
- /// Builds the request uri based on the parameters set by the user
- /// </summary>
- /// <returns></returns>
- private IHttpRequest CreateRequest(IHttpClient client) {
- var retval = client.CreateRequest(this.designDocument + "/_view/" + this.indexName);
-
- AddOptionalRequestParam(retval, "key", this.key);
- AddOptionalRequestParam(retval, "keys", this.keys);
- AddOptionalRequestParam(retval, "startkey", this.startKey);
- AddOptionalRequestParam(retval, "endkey", this.endKey);
- AddOptionalRequestParam(retval, "startkey_docid", this.startId);
- AddOptionalRequestParam(retval, "endkey_docid", this.endId);
- AddOptionalRequestParam(retval, "skip", this.skip);
- AddOptionalRequestParam(retval, "limit", this.limit);
-
- AddOptionalRequestParam(retval, "inclusive_end", this.inclusive);
- AddOptionalRequestParam(retval, "descending", this.descending);
- AddOptionalRequestParam(retval, "reduce", this.reduce);
- AddOptionalRequestParam(retval, "group", this.group);
- AddOptionalRequestParam(retval, "group_level", this.groupAt);
-
- if (this.stale != null)
- switch (this.stale.Value) {
- case StaleMode.AllowStale:
- retval.AddParameter("stale", "ok");
- break;
- case StaleMode.UpdateAfter:
- retval.AddParameter("stale", "update_after");
- break;
- case StaleMode.False:
- retval.AddParameter("stale", "false");
- break;
- default: throw new ArgumentOutOfRangeException("stale: " + this.stale);
- }
-
- if (this.onError != null)
- {
- switch (onError.Value) {
- case OnErrorMode.Continue:
- retval.AddParameter("on_error", "continue");
- break;
- case OnErrorMode.Stop:
- retval.AddParameter("on_error", "stop");
- break;
- default: throw new ArgumentOutOfRangeException("on_error: " + this.onError);
- }
- }
-
- return retval;
- }
-
- protected IHttpResponse GetResponse() {
- Debug.Assert(this.clientLocator != null);
-
- var client = this.clientLocator.Locate(this.designDocument);
- if (client == null) {
- if (log.IsErrorEnabled)
- log.WarnFormat("View {0} was mapped to a dead node, failing.", this);
-
- throw new InvalidOperationException();
- }
-
- var request = CreateRequest(client);
+ var viewParams = new Dictionary<string, string>();
+ var viewParamsBuilder = new ViewParamsBuilder();
- return request.GetResponse();
- }
+ viewParamsBuilder.AddOptionalParam("key", this.key);
+ viewParamsBuilder.AddOptionalParam("keys", this.keys);
+ viewParamsBuilder.AddOptionalParam("startkey", this.startKey);
+ viewParamsBuilder.AddOptionalParam("endkey", this.endKey);
+ viewParamsBuilder.AddOptionalParam("startkey_docid", this.startId);
+ viewParamsBuilder.AddOptionalParam("endkey_docid", this.endId);
- #region [ Request helpers ]
+ viewParamsBuilder.AddOptionalParam("inclusive_end", this.inclusive);
+ viewParamsBuilder.AddOptionalParam("descending", this.descending);
+ viewParamsBuilder.AddOptionalParam("reduce", this.reduce);
+ viewParamsBuilder.AddOptionalParam("group", this.group);
+ viewParamsBuilder.AddOptionalParam("group_level", this.groupAt);
+ viewParamsBuilder.AddOptionalParam("skip", this.skip);
- private static void AddOptionalRequestParam(IHttpRequest request, string name, bool? value) {
- if (value != null)
- request.AddParameter(name, value.Value ? "true" : "false");
- }
+ viewParamsBuilder.AddGreaterThanOneParam("limit", this.limit);
- private static void AddOptionalRequestParam(IHttpRequest request, string name, int? value) {
- if (value != null)
- request.AddParameter(name, value.Value.ToString(System.Globalization.CultureInfo.InvariantCulture));
- }
+ viewParamsBuilder.AddStaleParam(this.stale);
+ viewParamsBuilder.AddOnErrorParam(this.onError);
- private static void AddOptionalRequestParam<T>(IHttpRequest request, string name, T value)
- where T : IConvertible {
- if (value != null)
- request.AddParameter(name, value.ToString(System.Globalization.CultureInfo.InvariantCulture));
+ return this.ViewHandler.TransformResults<T>(rowTransformer, viewParamsBuilder.Build());
}
- #endregion
-
#region [ IView ]
public IView<T> Limit(int value) {
View
169 src/Couchbase/CouchbaseViewHandler.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+using System.Diagnostics;
+using System.IO;
+
+namespace Couchbase
+{
+ internal class CouchbaseViewHandler
+ {
+ protected static readonly Enyim.Caching.ILog log = Enyim.Caching.LogManager.GetLogger(typeof(CouchbaseViewHandler));
+
+ public ICouchbaseClient Client { get; private set; }
+ public IHttpClientLocator ClientLocator { get; private set; }
+ public string DesignDocument { get; private set; }
+ public string ViewPath { get; private set; }
+ public string IndexName { get; private set; }
+
+ internal CouchbaseViewHandler(ICouchbaseClient client, IHttpClientLocator clientLocator, string designDocument, string indexName, string viewPath = "_view")
+ {
+ this.Client = client;
+ this.ClientLocator = clientLocator;
+ this.DesignDocument = designDocument;
+ this.IndexName = indexName;
+ this.ViewPath = viewPath;
+ }
+
+ public int TotalRows { get; set; }
+
+ public bool MoveToArray(JsonReader reader, int depth, string name)
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == Newtonsoft.Json.JsonToken.PropertyName
+ && reader.Depth == depth
+ && ((string)reader.Value) == name)
+ {
+ if (!reader.Read()
+ || (reader.TokenType != Newtonsoft.Json.JsonToken.StartArray
+ && reader.TokenType != Newtonsoft.Json.JsonToken.Null))
+ throw new InvalidOperationException("Expecting array named '" + name + "'!");
+
+ // we skip the deserialization if the array is null
+ return reader.TokenType == Newtonsoft.Json.JsonToken.StartArray;
+ }
+ }
+
+ return false;
+ }
+
+ public IEnumerator<T> TransformResults<T>(Func<JsonReader, T> rowTransformer, IDictionary<string, string> viewParams)
+ {
+ var response = GetResponse(viewParams);
+ Debug.Assert(response != null);
+
+ using (var sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8, true))
+ using (var jsonReader = new JsonTextReader(sr))
+ {
+
+ while (jsonReader.Read())
+ {
+ if (jsonReader.TokenType == JsonToken.PropertyName && jsonReader.Depth == 1)
+ {
+ if (jsonReader.Value as string == "total_rows" && jsonReader.Read())
+ {
+ TotalRows = Convert.ToInt32(jsonReader.Value);
+ }
+ else if (jsonReader.Value as string == "rows" && jsonReader.Read())
+ {
+ // position the reader on the first "rows" field which contains the actual resultset
+ // this way we do not have to deserialize the whole response twice
+ // read until the end of the rows array
+ while (jsonReader.Read() && jsonReader.TokenType != Newtonsoft.Json.JsonToken.EndArray)
+ {
+ var row = rowTransformer(jsonReader);
+ yield return row;
+ }
+
+ if (MoveToArray(jsonReader, 1, "errors"))
+ {
+ var errors = Json.Parse(jsonReader);
+ var formatted = String.Join("\n", FormatErrors(errors as object[]).ToArray());
+ if (String.IsNullOrEmpty(formatted)) formatted = "<unknown>";
+
+ throw new InvalidOperationException("Cannot read view: " + formatted);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected static IEnumerable<string> FormatErrors(object[] list)
+ {
+ if (list == null || list.Length == 0)
+ yield break;
+
+ foreach (IDictionary<string, object> error in list)
+ {
+ object reason;
+ object from;
+
+ if (!error.TryGetValue("from", out from)) continue;
+ if (!error.TryGetValue("reason", out reason)) continue;
+
+ yield return from + ": " + reason;
+ }
+ }
+
+ /// <summary>
+ /// Builds the request uri based on the parameters set by the user
+ /// </summary>
+ /// <returns></returns>
+ public IHttpRequest CreateRequest(IHttpClient client, Dictionary<string, string> viewParams = null)
+ {
+ var retval = client.CreateRequest(this.DesignDocument + "/" + this.ViewPath + "/" + this.IndexName);
+ return retval;
+ }
+
+ public IHttpResponse GetResponse(IDictionary<string, string> viewParams)
+ {
+ Debug.Assert(this.ClientLocator != null);
+
+ var client = this.ClientLocator.Locate(this.DesignDocument);
+ if (client == null)
+ {
+ if (log.IsErrorEnabled)
+ log.WarnFormat("View {0} was mapped to a dead node, failing.", this);
+
+ throw new InvalidOperationException();
+ }
+
+ var request = CreateRequest(client);
+
+ if (viewParams != null)
+ {
+ foreach (var param in viewParams)
+ {
+ request.AddParameter(param.Key, param.Value.ToString());
+ }
+ }
+
+ return request.GetResponse();
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
7 src/Couchbase/CouchbaseView`1.cs
@@ -8,13 +8,14 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
+using Couchbase.Helpers;
namespace Couchbase {
internal class CouchbaseView<T> : CouchbaseViewBase<T> {
private bool _shouldLookupDocById = false;
- internal CouchbaseView(IMemcachedClient client, IHttpClientLocator clientLocator,
+ internal CouchbaseView(ICouchbaseClient client, IHttpClientLocator clientLocator,
string designDocument, string indexName, bool shouldLookupDocById = false,
string pagedViewIdProperty = null, string pagedViewKeyProperty = null)
: base(client, clientLocator, designDocument, indexName)
@@ -35,8 +36,8 @@ public override IEnumerator<T> GetEnumerator()
if (_shouldLookupDocById)
{
var key = Json.ParseValue(jr, "id") as string;
- var json = client.Get<string>(key);
- var jsonWithId = addIdToJson(json, key); //_id is omitted from the Json return by Get
+ var json = ViewHandler.Client.Get<string>(key);
+ var jsonWithId = DocHelper.InsertId(json, key);//_id is omitted from the Json return by Get
return JsonConvert.DeserializeObject<T>(jsonWithId);
}
else
View
40 src/Couchbase/Helpers/DocHelper.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Couchbase.Helpers
+{
+ public static class DocHelper
+ {
+ public static string InsertId(string json, string id)
+ {
+ if (!json.Contains("\"_id\""))
+ {
+ return json.Insert(1, string.Concat("\"_id\":", "\"", id, "\","));
+ }
+ return json;
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
2 src/Couchbase/ICouchbaseClient.cs
@@ -20,6 +20,8 @@ public interface ICouchbaseClient : IMemcachedClient, ICouchbaseResultsClient
IView<IViewRow> GetView(string designName, string viewName);
IView<T> GetView<T>(string designName, string viewName, bool shouldLookupDocById = false);
IDictionary<string, object> Get(IView view);
+ ISpatialView<ISpatialViewRow> GetSpatialView(string designName, string viewName);
+ ISpatialView<T> GetSpatialView<T>(string designName, string viewName, bool shouldLookupDocById = false);
}
}
View
2 src/Couchbase/ICouchbaseView`1.cs
@@ -11,7 +11,7 @@ public interface IView<T> : IEnumerable<T>
/// <summary>
/// TotalRows that would be returned by view, regardless of filters
/// </summary>
- int TotalRows { get; set; }
+ int TotalRows { get; }
/// <summary>
/// The view will return only the specified number of items.
View
53 src/Couchbase/ISpatialViewRow.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Couchbase
+{
+ public interface ISpatialViewRow
+ {
+ /// <summary>
+ /// Returns the id of the item referenced by this row. This id can be used to
+ /// perform the standard (Set/Get/Remove/etc.) operations on the item.
+ /// </summary>
+ string Id { get; set; }
+
+ /// <summary>
+ /// Bounding box of indexed coordinates from document
+ /// </summary>
+ float[] BoundingBox { get; set; }
+
+ /// <summary>
+ /// Structure containing geometry data (e.g., coordinates, type).
+ /// </summary>
+ SpatialViewGeometry Geometry { get; set; }
+
+ /// <summary>
+ /// Value emitted by map function
+ /// </summary>
+ object Value { get; set; }
+
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
61 src/Couchbase/ISpatialView`1.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Couchbase
+{
+ public interface ISpatialView<T> : IEnumerable<T>
+ {
+ /// <summary>
+ /// The view will return only the specified number of items.
+ /// </summary>
+ /// <param name="value">The number of items to return.</param>
+ /// <returns>A new <see cref="T:Couchbase.ISpatialView<T>"/> instance that contains the specified number of items from the start of the index in the view.</returns>
+ ISpatialView<T> Limit(int value);
+
+ /// <summary>
+ /// Bypasses the specified number of elements in the view then returns the remaining items.
+ /// </summary>
+ /// <param name="value">The number of elements to skip before returning the remaining items.</param>
+ /// <returns></returns>
+ /// <returns>A <see cref="T:Couchbase.ISpatialView"/> that contains the items that occur after the specified index in the view.</returns>
+ ISpatialView<T> Skip(int value);
+
+ /// <summary>
+ /// Couchbase will not update the view before returning the data even if it contains stale values. Use this mode if you favor improved query latency over data constistency.
+ /// </summary>
+ /// <param name="value"></param>
+ /// <returns>A new <see cref="T:Couchbase.ISpatialView<T>"/> instance that includes the stale items from the view.</returns>
+ ISpatialView<T> Stale(StaleMode mode);
+
+ /// <summary>
+ /// Bounding box for all rows to be returned by spatial view query
+ /// </summary>
+ /// <param name="value"></param>
+ /// <returns>A new <see cref="T:Couchbase.ISpatialView<T>"/> instance that includes all records within the bounding box.</returns>
+ ISpatialView<T> BoundingBox(float lowerLeftLong, float lowerLeftLat, float upperRightLong, float upperRightLat);
+
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
38 src/Couchbase/SpatialViewGeometry.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Couchbase
+{
+ public class SpatialViewGeometry
+ {
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("coordinates")]
+ public float[] Coordinates { get; set; }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
45 src/Couchbase/SpatialViewRow.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Couchbase
+{
+ public class SpatialViewRow : ISpatialViewRow
+ {
+
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("bbox")]
+ public float[] BoundingBox { get; set; }
+
+ [JsonProperty("geometry")]
+ public SpatialViewGeometry Geometry { get; set; }
+
+ [JsonProperty("value")]
+ public object Value { get; set; }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
View
126 src/Couchbase/ViewParamsBuilder.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+
+namespace Couchbase {
+
+ public enum StaleMode { AllowStale, UpdateAfter, False }
+
+ public enum OnErrorMode { Continue, Stop }
+
+ public class ViewParamsBuilder {
+
+ private readonly Dictionary<string, string> _viewParams;
+
+ public ViewParamsBuilder() {
+ _viewParams = new Dictionary<string, string>();
+ }
+
+ public void AddParam(string key, string value)
+ {
+ _viewParams.Add(key, value);
+ }
+
+ public void AddOptionalParam(string key, bool? value)
+ {
+ if (value != null && value.HasValue)
+ {
+ _viewParams.Add(key, value.Value ? "true" : "false");
+ }
+ }
+
+ public void AddOptionalParam(string key, int? value)
+ {
+ if (value != null && value.HasValue)
+ {
+ _viewParams.Add(key, value.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ public void AddGreaterThanOneParam(string key, int? value)
+ {
+ if (value != null && value.HasValue && value.Value > 0)
+ {
+ _viewParams.Add(key, value.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ public void AddOptionalParam<T>(string key, T value) where T : IConvertible
+ {
+ if (value != null)
+ {
+ _viewParams.Add(key, value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ public void AddStaleParam(StaleMode? stale)
+ {
+ if (stale != null)
+ {
+ switch (stale.Value)
+ {
+ case StaleMode.AllowStale:
+ _viewParams.Add("stale", "ok");
+ break;
+ case StaleMode.UpdateAfter:
+ _viewParams.Add("stale", "update_after");
+ break;
+ case StaleMode.False:
+ _viewParams.Add("stale", "false");
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("stale: " + stale);
+ }
+ }
+ }
+
+ public void AddOnErrorParam(OnErrorMode? onError)
+ {
+ if (onError != null)
+ {
+ switch (onError.Value)
+ {
+ case OnErrorMode.Continue:
+ _viewParams.Add("on_error", "continue");
+ break;
+ case OnErrorMode.Stop:
+ _viewParams.Add("on_error", "stop");
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("on_error: " + onError);
+ }
+ }
+ }
+
+ public Dictionary<string, string> Build()
+ {
+ return _viewParams.Count == 0 ? null : _viewParams;
+ }
+
+
+
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion

0 comments on commit 48cc56f

Please sign in to comment.
Something went wrong with that request. Please try again.