Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Views creation via HasViews syntax #139

Open
LoloActemium opened this issue Aug 17, 2021 · 5 comments
Open

Views creation via HasViews syntax #139

LoloActemium opened this issue Aug 17, 2021 · 5 comments
Labels
enhancement New feature or request

Comments

@LoloActemium
Copy link

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.

@matteobortolazzo
Copy link
Owner

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

@LoloActemium
Copy link
Author

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.

@AlexandrSHad
Copy link
Contributor

We are going to use tooling like this.
Maybe you also can consider that approach.

@LoloActemium
Copy link
Author

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.

@matteobortolazzo
Copy link
Owner

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

@matteobortolazzo matteobortolazzo added the enhancement New feature or request label Sep 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants