This blog explores use of the RedisJSON datatype in NetCore applications. It provides sample C# code that you can modify and use in your own applications. In all the examples shown, we'll be using the .NET client NReJSON (courtesy, Tommy Hanks et al).
Prerequisites The samples reference the following packages from nuget.org:
a) StackExchange.Redis -Version 2.1.58 b) NReJSON -Version 3.1.0 c) Newtonsoft.Json -Version 12.0.3
The samples were developed and tested with the versions shown; I imagine they'll work with later versions.
Sample Data
For this exercise, we'll need to create a RedisJSON datatype. We'll create a controller with a POCO object UserInfo that will provide the initial data for the app. The controller is shown below.
To keep the code simple and to the point, I am creating the data in the constructor and also hard-coding the IP address of the redis server. Included in the UserInfo is "rank". This is just to demonstrate use of the INCR command in a later example. Feel free to use DI and other methods to improve your implementation.
I am also using [HttpGet] for all the API endpoints, even if the method changes data, – again this is to keep things simple.
At any point you can verify the initial (non-RedisJSON) data using this code:
The next section of code creates the RedisJSON record and verifies that it is correct. Note: throughout this sample, I am using the format userprofile:useremail , in this case – "userprofile:bobjames@sample.com" – as the key.
Changing Values With the RedisJSON record created, we can try to change some properties. The code below shows how to change the "state" and the "fullName"
Incrementing Numeric Values Below is a sample on how to increment a numeric value. Here, we are incrementing the rank by 3.
Note: in the sample above, you can use a negative number if you want to decrement the number.
NReJSON also has the JsonMultiplyNumberAsync method for multiplying a numeric value. The code is similar to the above.
Getting Multiple Properties Redis Records can be 512 megabytes in size. If you have huge JSON records you may want to limit your queries to specific keys – for the same reasons why you may not want to limit use of SELECT * in SQL queries – and instead use SELECT column1, column3... instead.
The example below illustrates how to select fullName, state and zip from the RedisJSON record.
Important Notes a) In this example the record is returned with preceding periods (".") for the properties because they are actually redis key/value pairs.
{".fullName":"Bob T Jones",".address.state":"New York",".address.zip":"12345"}
b) If you include a key (eg .middleInitial ) that does not exist, you will get a RedisServerException error and no records will be returned.
Adding a New Property In the .address.zip key on the preceding samples we had a zip code "12345 Supposing we have to add a new field, zip+4, without changing the original zip. The example below shows how to do that. Note this requires just adding the value to a new key, eg, .address.zipPlusFour as shown in the example below.
Adding Whole Objects to RedisJSON Datatype The preceding example shows how to add a new property to the JSON record. We can use the same approach to add entire objects. Let's say we wanted to add a shipTo address to our current .address key. In our C# code we will create a new Address object and add it as shown below.
With this code implemented, we can then access the original street using the key .address.street and the shipTo street as .address.shipTo.street.
Implementing New Features/Executing Direct Commands As features are added to Redis, there may be commands that may not yet be implemented in your RedisJSON client. For instance, as of the time of this article (8/16/2020), the JSON.STRAPPEND command had not been implemented in our redis client NReJSON. Thanks to Marc Gravell we can use the StackExchange.Redis Execute/ExecuteAsync methods to implement this and other new or unimplemented commands.
Below is an example of how we can run the JSON.STRAPPEND command to add " Boulevard" to the key ".address.shipTo.street".
Notes: a) The JSON.STRAPPEND command returns an integer – the length of the updated string. b) You are encouraged to wrap the Execute method in a try/catch because if the path is invalid, a RedisServerException will be thrown.