Null string value on retrieving documents from bucket view


#1

Operating Couchbase server 2.5.1 with a bucket view configured like

function (doc, meta) {
  if (meta.type == "json" &&
      meta.id.indexOf("ExchangeRoomSub:") === 0)
  {
    emit(meta.id, null);
  }
}

in order to present stored documents like

{
   "LastCheck": "2015-03-11T07:50:40.0227883Z",
   "LastNotification": null,
   "FromTicketId": 7388719553030940,
   "SigninId": "user@address.com",
   "RoomAddress": "room@address.com",
   "SubscriptionId": "JwBzaXhwcjAybWIwODc5LmFwY3ByZDAyLnByb2Qub3V0bG9vay5jb20QAAAA4qBzBDolEkSL0fmqe2I6F2smzvQ0KdIIEAAAAALPfNEhdhlMizi0BS2fXRY=",
   "LastWatermark": "AQAAABjYlN1rB1hFpRGKcdo4uJUvl8IBAAAAAAA="
}

We interact with Couchbase using .NET SDK v1.3.5, with view extraction code to deserialise the view items via JSON.NET.

public IEnumerable<TEntity> GetView()
{
	var view = _CouchBaseClient.GetView(_ViewName, _ViewName);
	var items = view.Select(r => r.GetItem());
	return items.Select(i => JsonConvert.DeserializeObject<TEntity>(i as string));
}

This works most of the time. Sometimes it appears the item object ends up null.

Value cannot be null.
Parameter name: value
System.ArgumentNullException
Newtonsoft.Json
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Gumbuya.Services.Core.CouchBaseDiskRepository`1.<GetView>b__7(Object i)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)

Under what condition would a document item turn up null when there is proper value being stored?


How "strictly" are temporary documents stored in buckets?
#2

On discussing the volatility of temporary items in How “strictly” are temporary documents stored in buckets? it seems very plausible this case is due to the actual document item “evaporating” from the bucket, thus the view ends up with a null item when it has not synced itself completely yet.


#3

At any rate it seems necessary to filter out any possible underlying null document item, before attempting to deserialise back to the data object.

public IEnumerable<TEntity> GetViewItems()
{
	var view = _CouchBaseClient.GetView(_ViewName, _ViewName);
	var items = view.Select(r => r.GetItem());

	// BUG-447: Some times for unknown reason Couchbase underlying document item is null.
	var concreteItems = items.Where(i => i != null);
	if (view.Count() > concreteItems.Count())
	{
		ActivityLogger.Warn(string.Format("[CouchBaseDiskRepository<{0}>] view '{1}' has {2} items seemingly with null value.",
			typeof(TEntity).Name,
			_ViewName,
			(view.Count() - concreteItems.Count()) ));
	}
	return concreteItems.Select(c => JsonConvert.DeserializeObject<TEntity>(c as string));
}

#4

Hi, just a quick follow up–is the approach mentioned above filtering out nulls working? Do you have any follow up questions?


#5

Hi @tgreenstein yes we’ve had to make the additional null check after GetItem() to ensure we don’t attempt to deserialise any null objects that happen to be “hiding” behind the view item. With that the program logic will not crash.


#6

I don’t know why my data long existed but this morning I access through GetView(…) and I get null value. After 3 tries, I got the right result. Can anyone help me to fix this problem? Tks :fearful: This problem has lasted for weeks with me