couchdb-net
couchdb-net copied to clipboard
Views creation via HasViews syntax
Hi,
I'm currently using your lib to log OPC/UA events in CouchDB database (and I like it :)). I use your lib because I'm a CouchDB noob and I'm an EF Cpore user on some other projects (using SQL Server as DB). Is there a way to create views within the OnDatabaseCreating(....) function ? An HasView(...) syntax would be nice, but I could find it. Or should I have to implement it myself ?
Kind regards, Laurent.
Hi,
thanks for the kind words :)
No there's not even a method to create views normally. This is because views are Javascript functions and since I didn't want to invest in C# to JS I implemented only the reading
Hi, And what about "just" implementing a view creation with Js as simple string ? In a curl fashion, passing the Js in a POST request. Kind Regards, Laurent.
We are going to use tooling like this. Maybe you also can consider that approach.
Hello, I implemented it this way (see code below) in my DatabaseContext file. It's based on the lib source code for Login/Logout and GetName.
//Add eventTypes view
var viewDefinition = new View()
{
Name = "eventTypes",
Map = "function (doc) {\n emit(doc.eventTypeName, null);\n}",
Reduce = "function (keys, values, rereduce) {\n return true;\n}"
};
HasView<ServerEvent>("Events", viewDefinition);
It's enough for me, as it sends an 400 error when the Js code is not well formatted (does not check document properties names, but not a problem for me). I had to copy/adapt some functions because allmost all interesting functions/properties are marked as internal :) I can provide the complete code, if someone is intereted. If I found time, I will try to implement it in the lib itself, and PR it.
HasView function code :
private void HasView<TSource>(string documentName, View viewDefinition)
{
using (var flurlClient = GetConfiguredClient())
{
//Get database name
var database = typeof(TSource).GetName();
//Log in to database server
string cookieToken = LoginAsync(flurlClient).GetAwaiter().GetResult();
//Trying to get the design document containing the views
var flurlResponse = flurlClient.Request(_databaseEndpoint).AppendPathSegment($"/{database}/_design/{documentName}")
.WithCookie("AuthSession", cookieToken)
.AllowHttpStatus("404")
.GetAsync().GetAwaiter().GetResult();
if (flurlResponse.StatusCode == 404)
{
//Create new view
var designDoc = new DesignDocument()
{
Language = "javascript",
Views = new Dictionary<string, View>()
};
designDoc.Views.Add(viewDefinition.Name, viewDefinition);
var test = flurlClient.Request(_databaseEndpoint).AppendPathSegment($"/{database}/_design/{documentName}")
.WithCookie("AuthSession", cookieToken)
.AllowHttpStatus("400")
.PutJsonAsync(designDoc).GetAwaiter().GetResult();
if (test.StatusCode == 400)
{
throw new Exception($"Invalid map or reduce source code in view {documentName}:{viewDefinition.Name}");
}
}
else
{
var views = flurlResponse.GetJsonAsync<DesignDocument>().GetAwaiter().GetResult();
if (!views.Views.ContainsKey(viewDefinition.Name))
{
views.Views.Add(viewDefinition.Name, viewDefinition);
//create view
var test = flurlClient.Request(_databaseEndpoint).AppendPathSegment($"/{database}/_design/{documentName}")
.WithCookie("AuthSession", cookieToken)
.AllowHttpStatus("400")
.PutJsonAsync(views).GetAwaiter().GetResult();
if (test.StatusCode == 400)
{
throw new Exception($"Invalid map or reduce source code in view {documentName}:{viewDefinition.Name}");
}
}
}
LogoutAsync(flurlClient).GetAwaiter().GetResult();
}
}
Kind regards, Laurent.
Hi @LoloActemium ,
yes, I can consider implementing it, it's not a bad idea.
In the meanwhile, you can refactor your code using NewRequest() method in ICouchDatabase as it gives use authentication and the document URL for free.
A you should using async-await if possible