diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 5796a32..6b8b6f5 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -12,11 +12,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.100 - name: Restore dependencies run: dotnet restore - name: Build diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a13dd04..abf7e29 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,11 +10,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.100 - name: Restore dependencies run: dotnet restore - name: Build @@ -24,4 +24,4 @@ jobs: - name: Pack run: dotnet pack - name: Push - run: dotnet nuget push src/Elasticsearch.FSharp/bin/Debug/*.nupkg --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json + run: dotnet nuget push src/Elasticsearch.FSharp/bin/Release/*nupkg --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json diff --git a/src/Elasticsearch.FSharp/Elasticsearch.FSharp.fsproj b/src/Elasticsearch.FSharp/Elasticsearch.FSharp.fsproj index 65debcb..f05a343 100644 --- a/src/Elasticsearch.FSharp/Elasticsearch.FSharp.fsproj +++ b/src/Elasticsearch.FSharp/Elasticsearch.FSharp.fsproj @@ -13,9 +13,18 @@ fsharp elastic elasticsearch Compose type-checked ElasticSearch queries with the power of F# language https://github.com/dbarbashov/Elasticsearch.FSharp - https://github.com/dbarbashov/Elasticsearch.FSharp/blob/master/LICENSE.md + LICENSE.md + readme.md + true + snupkg + true + + + + + @@ -56,4 +65,8 @@ + + + + diff --git a/src/Elasticsearch.FSharp/Mapping/Json.fs b/src/Elasticsearch.FSharp/Mapping/Json.fs index 218b3cb..8646d8b 100644 --- a/src/Elasticsearch.FSharp/Mapping/Json.fs +++ b/src/Elasticsearch.FSharp/Mapping/Json.fs @@ -1,8 +1,12 @@ module Elasticsearch.FSharp.Mapping.Json +open System +open System.Runtime.InteropServices open Elasticsearch.FSharp.Mapping.DSL open Elasticsearch.FSharp.Utility +let [] private OpenSearchFlatObject = "flat_object" + type MappingSetting with member x.ToJson() = match x with @@ -12,19 +16,25 @@ type MappingSetting with Json.boolToString value type PropertyMapping with - member x.ToJson() = Json.makeObject [ + member x.ToJson([] usingOpenSearch) = Json.makeObject [ if not x.Enabled then yield Json.makeKeyValue "enabled" (Json.boolToString x.Enabled) if x.IgnoreMalformed then yield Json.makeKeyValue "ignore_malformed" (Json.boolToString x.IgnoreMalformed) - - match x.Type with - | Some t -> yield Json.makeKeyValue "type" (Json.quoteString t) - | None -> () + + let ``type`` = + x.Type + |> Option.map(fun t -> if usingOpenSearch && t = "flattened" then OpenSearchFlatObject else t) + |> Option.defaultValue "" + + if ``type`` |> String.IsNullOrEmpty |> not then + yield Json.makeKeyValue "type" (Json.quoteString ``type``) match x.IgnoreAbove with - | Some ia -> yield Json.makeKeyValue "ignore_above" (Json.uintToString ia) + | Some ia -> + if ``type``<> OpenSearchFlatObject then + yield Json.makeKeyValue "ignore_above" (Json.uintToString ia) | None -> () match x.Analyzer with @@ -39,7 +49,7 @@ type PropertyMapping with | Some props -> yield Json.makeKeyValue "properties" (Json.makeObject [ for p in props do - yield Json.makeKeyValue p.Key (p.Value.ToJson()) + yield Json.makeKeyValue p.Key (p.Value.ToJson(usingOpenSearch)) ]) | None -> () @@ -47,13 +57,13 @@ type PropertyMapping with | Some fields -> yield Json.makeKeyValue "fields" (Json.makeObject [ for f in fields do - yield Json.makeKeyValue f.Key (f.Value.ToJson()) + yield Json.makeKeyValue f.Key (f.Value.ToJson(usingOpenSearch)) ]) | None -> () ] type TypeMapping with - member x.ToJson() = Json.makeObject [ + member x.ToJson([] usingOpenSearch) = Json.makeObject [ match x.AllEnabled with | Some true -> yield @@ -64,14 +74,15 @@ type TypeMapping with yield Json.makeKeyValue "properties" (Json.makeObject [ for p in x.Properties do - yield Json.makeKeyValue p.Key (p.Value.ToJson()) + yield Json.makeKeyValue p.Key (p.Value.ToJson(usingOpenSearch)) ]) ] type ElasticMapping with - member x.ToJson(?includeTypeName) = Json.makeObject [ - let includeTypeName = Option.defaultValue true includeTypeName - + member x.ToJson( + [] includeTypeName, + [] usingOpenSearch) = Json.makeObject [ + match x.Settings with | Some settings -> yield Json.makeKeyValue "settings" (Json.makeObject [ @@ -82,17 +93,17 @@ type ElasticMapping with if includeTypeName then yield Json.makeKeyValue "mappings" (Json.makeObject [ - Json.makeKeyValue "_doc" (x.Mappings.ToJson()) + Json.makeKeyValue "_doc" (x.Mappings.ToJson(usingOpenSearch)) ]) else - yield Json.makeKeyValue "mappings" (x.Mappings.ToJson()) + yield Json.makeKeyValue "mappings" (x.Mappings.ToJson(usingOpenSearch)) ] - member x.ToPutMappingsJson() = [| + member x.ToPutMappingsJson([] usingOpenSearch) = [| for kv in x.Mappings.Properties do yield Json.makeObject [ Json.makeKeyValue "properties" (Json.makeObject [ - Json.makeKeyValue kv.Key (kv.Value.ToJson()) + Json.makeKeyValue kv.Key (kv.Value.ToJson(usingOpenSearch)) ]) ] |] \ No newline at end of file diff --git a/tests/Elasticsearch.FSharp.Tests/Elasticsearch.FSharp.Tests.fsproj b/tests/Elasticsearch.FSharp.Tests/Elasticsearch.FSharp.Tests.fsproj index 3a28a89..40c38e5 100644 --- a/tests/Elasticsearch.FSharp.Tests/Elasticsearch.FSharp.Tests.fsproj +++ b/tests/Elasticsearch.FSharp.Tests/Elasticsearch.FSharp.Tests.fsproj @@ -1,16 +1,17 @@  - net6.0 + net8.0 true + false - - - - - + + + + + diff --git a/tests/Elasticsearch.FSharp.Tests/Mapping.fs b/tests/Elasticsearch.FSharp.Tests/Mapping.fs index 89f2788..5f3e095 100644 --- a/tests/Elasticsearch.FSharp.Tests/Mapping.fs +++ b/tests/Elasticsearch.FSharp.Tests/Mapping.fs @@ -1,12 +1,10 @@ module Elasticsearch.FSharp.Tests.Mapping open System.Collections.Generic -open Elasticsearch.FSharp.Mapping.DSL -open NUnit.Framework - -open System.Text.RegularExpressions open Elasticsearch.FSharp.Mapping.Attributes +open Elasticsearch.FSharp.Mapping.DSL open Elasticsearch.FSharp.Mapping.Json +open NUnit.Framework [] type TestEntity = { @@ -19,66 +17,80 @@ type TestEntity = { [] [] title: string + + [] + baskets: string[] } -[] -let ``Type serializes correctly``() = +let inline private getBasketsProps usingOpenSearch = + if usingOpenSearch then + """"baskets": { "type":"flat_object" }""" + else + """"baskets": { "type":"flattened", "ignore_above":1000 }""" + +[] +[] +let ``Type serializes correctly``(usingOpenSearch: bool) = let mapping = generateElasticMapping typeof - let mappingJson = mapping.ToJson() + let mappingJson = mapping.ToJson(usingOpenSearch=usingOpenSearch) let expected = Helpers.removeWhitespace - """{ - "mappings": { - "_doc": { - "properties": { - "id": { + $"""{{ + "mappings": {{ + "_doc": {{ + "properties": {{ + "id": {{ "type": "long" - }, - "title": { + }}, + "title": {{ "type": "text", - "fields": { - "raw": { "type":"keyword" }, - "integer": { "ignore_malformed":true, "type":"integer" }, - "en": { "type":"text", "analyzer":"english" }, - "ru": { "type":"text", "analyzer":"russian" } - } - } - } - } - } - }""" + "fields": {{ + "raw": {{ "type":"keyword" }}, + "integer": {{ "ignore_malformed":true, "type":"integer" }}, + "en": {{ "type":"text", "analyzer":"english" }}, + "ru": {{ "type":"text", "analyzer":"russian" }} + }} + }}, + {getBasketsProps usingOpenSearch} + }} + }} + }} + }}""" let actual = mappingJson Assert.AreEqual(expected, actual) - -[] -let ``Type serializes correctly with excluded type name``() = + +[] +[] +let ``Type serializes correctly with excluded type name``(usingOpenSearch: bool) = let mapping = generateElasticMapping typeof - let mappingJson = mapping.ToJson(includeTypeName=false) + let mappingJson = mapping.ToJson(includeTypeName=false, usingOpenSearch=usingOpenSearch) let expected = Helpers.removeWhitespace - """{ - "mappings": { - "properties": { - "id": { + $"""{{ + "mappings": {{ + "properties": {{ + "id": {{ "type": "long" - }, - "title": { + }}, + "title": {{ "type": "text", - "fields": { - "raw": { "type":"keyword" }, - "integer": { "ignore_malformed":true, "type":"integer" }, - "en": { "type":"text", "analyzer":"english" }, - "ru": { "type":"text", "analyzer":"russian" } - } - } - } - } - }""" + "fields": {{ + "raw": {{ "type":"keyword" }}, + "integer": {{ "ignore_malformed":true, "type":"integer" }}, + "en": {{ "type":"text", "analyzer":"english" }}, + "ru": {{ "type":"text", "analyzer":"russian" }} + }} + }}, + {getBasketsProps usingOpenSearch} + }} + }} + }}""" let actual = mappingJson Assert.AreEqual(expected, actual) - -[] -let ``Type serializes correctly with settings``() = + +[] +[] +let ``Type serializes correctly with settings``(usingOpenSearch: bool) = let mapping = generateElasticMapping typeof let mapping = { mapping with @@ -91,42 +103,45 @@ let ``Type serializes correctly with settings``() = |> Dictionary |> Some } - let mappingJson = mapping.ToJson(includeTypeName=false) + let mappingJson = mapping.ToJson(includeTypeName=false, usingOpenSearch=usingOpenSearch) let expected = Helpers.removeWhitespace - """{ - "settings": { + $"""{{ + "settings": {{ "number_of_shards": "5", "number_of_replicas": "2" - }, - "mappings": { - "properties": { - "id": { + }}, + "mappings": {{ + "properties": {{ + "id": {{ "type": "long" - }, - "title": { + }}, + "title": {{ "type": "text", - "fields": { - "raw": { "type":"keyword" }, - "integer": { "ignore_malformed":true, "type":"integer" }, - "en": { "type":"text", "analyzer":"english" }, - "ru": { "type":"text", "analyzer":"russian" } - } - } - } - } - }""" + "fields": {{ + "raw": {{ "type":"keyword" }}, + "integer": {{ "ignore_malformed":true, "type":"integer" }}, + "en": {{ "type":"text", "analyzer":"english" }}, + "ru": {{ "type":"text", "analyzer":"russian" }} + }} + }}, + {getBasketsProps usingOpenSearch} + }} + }} + }}""" let actual = mappingJson Assert.AreEqual(expected, actual) - -[] -let ``Type serializes correctly to put mappings json``() = + +[] +[] +let ``Type serializes correctly to put mappings json``(usingOpenSearch: bool) = let mapping = generateElasticMapping typeof - let mappingJson = mapping.ToPutMappingsJson() + let mappingJson = mapping.ToPutMappingsJson(usingOpenSearch) let expected = [| """{"properties":{"id": { "type": "long" }}}""" """{"properties":{"title": { "type": "text", "fields": { "raw": { "type":"keyword" }, "integer": { "ignore_malformed":true, "type":"integer" }, "en": { "type":"text", "analyzer":"english" }, "ru": { "type":"text", "analyzer":"russian" } } }}}""" + $"""{{"properties":{{ {getBasketsProps usingOpenSearch} }}}}""" |] |> Array.map Helpers.removeWhitespace let actual = mappingJson @@ -206,5 +221,5 @@ let ``Recursive type serializes correctly``() = } }""" let actual = mappingJson - printf "%s" mappingJson + printf $"%s{mappingJson}" Assert.AreEqual(expected, actual) \ No newline at end of file