How to make info/document that has the same ID append it's formation to the document(sub-document/nested document?)

For example, if I have a document with that ID, and another document with that ID is trying to insert, it will add it’s information to the existing document.

        var config = new ClientConfiguration
        {
            Servers = new List<Uri>
            {
              new Uri("couchbase://localhost/"),

            }
        };

        using (var cluster = new Cluster(config))
        {
            using (var bucket = cluster.OpenBucket("BeaconListN1ql"))
            {

                string id = beacon.SerialNumber;
                
                //Attributes = new Dictionary<string, object>
                //    {
                //        {"BluetoothAddress",  beacon.BluetoothAddress},
                //        {"BluetoothName",  beacon.BluetoothName},
                //        {"Id1", beacon.Id1},
                //        {"Id2",  beacon.Id2},
                //        {"Id3", beacon.Id3},
                //        {"SerialNumber", beacon.SerialNumber },
                //        {"ReceiverId", beacon.ReceiverId },
                //        {"Manufacturer", beacon.Manufacturer },
                //        {"ServiceUuid", beacon.ServiceUuid }
                //    }



                var doc = new
                {
                    BluetoothAddress = beacon.BluetoothAddress,
                    BluetoothName = beacon.BluetoothName,
                    Id1 = beacon.Id1,
                    Id2 = beacon.Id2,
                    Id3 = beacon.Id3,
                    SerialNumber = beacon.SerialNumber,
                    ReceiverId = beacon.ReceiverId,
                    Manufacturer = beacon.Manufacturer,
                    ServiceUuid = beacon.ServiceUuid,
                };

                if (!bucket.Exists(beacon.SerialNumber))
                {
                    bucket.Insert(new Document<dynamic>
                    {
                        Id = id,
                        Content = doc
                    });
                }

                else
                {
                    //InsertExample(IBucket bucket, string id, string path, string value)


                    bucket.MutateIn<dynamic>(id).Insert(id, doc, true).Execute();  

                }
            }
        }

This does not work as it will try add to the id and obviously won’t insert after the second input. I want it so all that information regarding the beacon entries can be in one document with the id of beacon serial number.

edit- I believe the document id and key(IOperationResult Insert(string key, T value); ) are the same thing? which means you can’t append the items like I want to since you can’t have duplicate keys?

@krnforsale -

  • You can use IBucket.Replace(key, value) or IBucket.Replace(document) - this will replace an existing document with a new one for a given key.
  • Yes, Id and key are the same thing…the Document API just has a slightly different interface.
  • You could also use the SubDocument API as well to add elements to a document. This will likely give you better performance.

-Jeff

@jmorris I don’t want to replace the values at a given key, I want to add values if that key exists. My code up there is me trying to use SubDocument API using MutateIn().

for example, I would want it to display like this.

[
  {
    "BeaconListN1ql": {
    
        "attributes": {
          "bluetoothAddress": "0C:F3:EE:08:A1:B0",
          "bluetoothName": "EMBeacon00185",
          "id1": "1",
          "id2": "2",
          "id3": "3",
          "manufacturer": 65194,
          "receiverId": "42008780c4b9b329",
          "serialNumber": "888",
          "serviceUuid": 65194
      },
        "attributes": {
          "bluetoothAddress": "0C:F3:EE:08:A1:B0",
          "bluetoothName": "EMBeacon00185",
          "id1": "11",
          "id2": "22",
          "id3": "33",
          "manufacturer": 65194,
          "receiverId": "42008780c4b9b329",
          "serialNumber": "888",
          "serviceUuid": 65194
      },
        "attributes": {
          "bluetoothAddress": "0C:F3:EE:08:A1:B0",
          "bluetoothName": "EMBeacon00185",
          "id1": "111",
          "id2": "222",
          "id3": "333",
          "manufacturer": 65194,
          "receiverId": "42008780c4b9b329",
          "serialNumber": "888",
          "serviceUuid": 65194
      }
    }
  }
]

@krnforsale -

Then sub document API is your tool! Read this: https://blog.couchbase.com/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted/

The Collection API may also work for you: https://dzone.com/articles/net-core-list-queue-and-dictionary-data-structures

-Jeff

@jmorris

so I’m using queue to Enqueue my beacon infromation and it works perfectly! Now I’m trying to use n1ql query for my get method and I’m having trouble getting all the information. I realized I’m only getting the first beacon entry because result.Rows returns one element, an array of BeaconInfoN1ql. I wanted to iterate through that array and add each to a list.

try
         {
             var cluster = new Cluster(new ClientConfiguration());
             using (var bucket = cluster.OpenBucket("BeaconInfoN1ql"))
             {
                 string query = "SELECT * FROM `BeaconInfoN1ql`";
                 var queryRequest = new QueryRequest(query);
                 var result = bucket.Query<dynamic>(queryRequest);

                 foreach (var row in result.Rows)
                  {

                      int i = 0;
                      var beacon = new Beacon()
                      {
                          SerialNumber = row.BeaconInfoN1ql[i].serialNumber,
                          ReceivedDate = Convert.ToDateTime(row.BeaconInfoN1ql[i].receivedDate),
                          ReceiverId = row.BeaconInfoN1ql[i].receiverId,
                          Distance = Convert.ToDouble(row.BeaconInfoN1ql[i].distance),
                          Rssi = Convert.ToInt32(row.BeaconInfoN1ql[i].rssi),
                          NewDistance = Convert.ToDouble(row.BeaconInfoN1ql[i].newDistance),
                          DistanceTesting = Convert.ToDouble(row.BeaconInfoN1ql[i].distanceTesting),
                      };
                      i++;
                      _beaconsList.Add(beacon);
                  }
             }
             return _beaconsList;

my result.Rows looks like this

result.Rows=
{{
“BeaconInfoN1ql”: [
{
“distance”: 2.2705747109792007,
“distanceTesting”: 22,
“newDistance”: 22,
“receivedDate”: “0001-01-01T00:00:00”,
“receiverId”: “42008780c4b9b329”,
“rssi”: -73,
“serialNumber”: “888”
},
{
“distance”: 2.2705747109792007,
“distanceTesting”: 22,
“newDistance”: 22,
“receivedDate”: “0001-01-01T00:00:00”,
“receiverId”: “42008780c4b9b329”,
“rssi”: -73,
“serialNumber”: “888”
},
{
“distance”: 2.2705747109792007,
“distanceTesting”: 22,
“newDistance”: 22,
“receivedDate”: “0001-01-01T00:00:00”,
“receiverId”: “42008780c4b9b329”,
“rssi”: -73,
“serialNumber”: “888”
},
{
“distance”: 2.2705747109792007,
“distanceTesting”: 22,
“newDistance”: 22,
“receivedDate”: “0001-01-01T00:00:00”,
“receiverId”: “42008780c4b9b329”,
“rssi”: -73,
“serialNumber”: “888”
},
{
“distance”: 2.2705747109792007,
“distanceTesting”: 33,
“newDistance”: 22,
“receivedDate”: “0001-01-01T00:00:00”,
“receiverId”: “42008780c4b9b329”,
“rssi”: -73,
“serialNumber”: “888”
}
]
}}

@krnforsale,

It looks like you’re missing a loop inside of your loop. You’re looping through all the queues, you need another loop to loop through all the items within a queue.

Alternatively, you can use the CouchbaseQueue object and pass in the document key(s) to the constructor. There might be a major performance difference if your N1QL query was just querying for keys, maybe you can try it out (or maybe @jmorris can speak to that).

@matthew.groves ah, thank you. I’ll look into looping through elements in the array. I’ll also look into using CouchbaseQueue object and pass in the document key.

1 Like