You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2023/03/01 19:21:25 UTC

[couchdb] 02/06: redo field abstraction

This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch import-nouveau-great-shuffle-wip
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ddff1ecbf4ef1ba5a52d8ef2baaeebd0ed4b7d09
Author: Robert Newson <rn...@apache.org>
AuthorDate: Sun Feb 26 23:50:32 2023 +0000

    redo field abstraction
---
 .../nouveau/api/document/DoubleDocValuesField.java |  40 --------
 .../couchdb/nouveau/api/document/DoubleField.java  |  43 ++++++--
 .../couchdb/nouveau/api/document/DoublePoint.java  |  41 --------
 .../apache/couchdb/nouveau/api/document/Field.java |   4 -
 .../nouveau/api/document/SortedDocValuesField.java |  40 --------
 .../api/document/SortedSetDocValuesField.java      |  40 --------
 .../nouveau/api/document/StoredDoubleField.java    |   4 +-
 .../nouveau/api/document/StoredStringField.java    |   4 +-
 .../couchdb/nouveau/api/document/StringField.java  |  39 ++++++--
 .../couchdb/nouveau/api/document/TextField.java    |  42 ++++++--
 .../nouveau/api/DocumentUpdateRequestTest.java     |   9 +-
 .../resources/fixtures/DocumentUpdateRequest.json  |   8 +-
 .../couchdb/nouveau/core/lucene4/Lucene4Index.java |  63 +++++-------
 .../couchdb/nouveau/core/lucene9/Lucene9Index.java |  72 ++++++-------
 java/nouveau/server/README.md                      |   8 +-
 .../apache/couchdb/nouveau/IntegrationTest.java    |  11 +-
 .../nouveau/core/ser/SerializationTest.java        |  42 ++++----
 share/server/nouveau.js                            | 111 ++++++++++-----------
 src/mango/src/mango_native_proc.erl                |  18 +---
 19 files changed, 252 insertions(+), 387 deletions(-)

diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleDocValuesField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleDocValuesField.java
deleted file mode 100644
index 64a706e39..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleDocValuesField.java
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public final class DoubleDocValuesField extends Field {
-
-    private final double value;
-
-    @JsonCreator
-    public DoubleDocValuesField(@JsonProperty("name") final String name,
-            @JsonProperty("value") final double value) {
-        super(name);
-        this.value = value;
-    }
-
-    @JsonProperty
-    public double getValue() {
-        return value;
-    }
-
-    @Override
-    public String toString() {
-        return "DoubleDocValuesField [name=" + name + ", value=" + value + "]";
-    }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java
index b11a4bd2d..11f662233 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java
@@ -13,21 +13,39 @@
 
 package org.apache.couchdb.nouveau.api.document;
 
+import javax.validation.constraints.NotNull;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+import io.dropwizard.jackson.JsonSnakeCase;
 
+@JsonSnakeCase
+@JsonInclude(value=Include.NON_DEFAULT)
 public final class DoubleField extends Field {
 
     private final double value;
 
-    private final boolean stored;
+    private final boolean store;
+
+    private final boolean facet;
+
+    private final boolean sortable;
 
     @JsonCreator
-    public DoubleField(@JsonProperty("name") final String name,
-            @JsonProperty("value") final double value, @JsonProperty("stored") final boolean stored) {
+    public DoubleField(
+        @NotNull @JsonProperty("name") final String name,
+        @NotNull @JsonProperty("value") final double value,
+        @JsonProperty("store") final boolean store,
+        @JsonProperty("facet") final boolean facet,
+        @JsonProperty("sortable") final boolean sortable) {
         super(name);
         this.value = value;
-        this.stored = stored;
+        this.store = store;
+        this.facet = facet;
+        this.sortable = sortable;
     }
 
     @JsonProperty
@@ -36,13 +54,24 @@ public final class DoubleField extends Field {
     }
 
     @JsonProperty
-    public boolean isStored() {
-        return stored;
+    public boolean isStore() {
+        return store;
+    }
+
+    @JsonProperty
+    public boolean isFacet() {
+        return facet;
+    }
+
+    @JsonProperty
+    public boolean isSortable() {
+        return sortable;
     }
 
     @Override
     public String toString() {
-        return "DoubleField [name=" + name + ", value=" + value + ", stored=" + stored + "]";
+        return "DoubleField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
+                + "]";
     }
 
 }
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoublePoint.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoublePoint.java
deleted file mode 100644
index 9733301a5..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoublePoint.java
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import java.util.Arrays;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public final class DoublePoint extends Field {
-
-    private final double[] value;
-
-    @JsonCreator
-    public DoublePoint(@JsonProperty("name") final String name, @JsonProperty("value") final double... value) {
-        super(name);
-        this.value = value;
-    }
-
-    @JsonProperty
-    public double[] getValue() {
-        return value;
-    }
-
-    @Override
-    public String toString() {
-        return "DoublePoint [name=" + name + ", value=" + Arrays.toString(value) + "]";
-    }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java
index 0eb9bcd4e..2fc90b29e 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java
@@ -25,11 +25,7 @@ import io.dropwizard.jackson.JsonSnakeCase;
     include = JsonTypeInfo.As.PROPERTY,
     property = "@type")
 @JsonSubTypes({
-    @JsonSubTypes.Type(value = DoubleDocValuesField.class, name = "double_dv"),
     @JsonSubTypes.Type(value = DoubleField.class, name = "double"),
-    @JsonSubTypes.Type(value = DoublePoint.class, name = "double_point"),
-    @JsonSubTypes.Type(value = SortedDocValuesField.class, name = "sorted_dv"),
-    @JsonSubTypes.Type(value = SortedSetDocValuesField.class, name = "sorted_set_dv"),
     @JsonSubTypes.Type(value = StoredDoubleField.class, name = "stored_double"),
     @JsonSubTypes.Type(value = StoredStringField.class, name = "stored_string"),
     @JsonSubTypes.Type(value = StringField.class, name = "string"),
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedDocValuesField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedDocValuesField.java
deleted file mode 100644
index d5cfe9bcc..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedDocValuesField.java
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package org.apache.couchdb.nouveau.api.document;
-
-import java.util.Arrays;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public final class SortedDocValuesField extends Field {
-
-    private final byte[] value;
-
-    @JsonCreator
-    public SortedDocValuesField(@JsonProperty("name") final String name, @JsonProperty("value") final byte[] value) {
-        super(name);
-        this.value = value;
-    }
-
-    @JsonProperty
-    public byte[] getValue() {
-        return value;
-    }
-
-    @Override
-    public String toString() {
-        return "SortedDocValuesField [name=" + name + ", value=" + Arrays.toString(value) + "]";
-    }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedSetDocValuesField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedSetDocValuesField.java
deleted file mode 100644
index bdf432a70..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/SortedSetDocValuesField.java
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package org.apache.couchdb.nouveau.api.document;
-
-import java.util.Arrays;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public final class SortedSetDocValuesField extends Field {
-
-    private final byte[] value;
-
-    @JsonCreator
-    public SortedSetDocValuesField(@JsonProperty("name") final String name, @JsonProperty("value") final byte[] value) {
-        super(name);
-        this.value = value;
-    }
-
-    @JsonProperty
-    public byte[] getValue() {
-        return value;
-    }
-
-    @Override
-    public String toString() {
-        return "SortedSetDocValuesField [name=" + name + ", value=" + Arrays.toString(value) + "]";
-    }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java
index 32210d19b..b880f1742 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java
@@ -13,6 +13,8 @@
 
 package org.apache.couchdb.nouveau.api.document;
 
+import javax.validation.constraints.NotNull;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -21,7 +23,7 @@ public final class StoredDoubleField extends Field {
     private final double value;
 
     @JsonCreator
-    public StoredDoubleField(@JsonProperty("name") final String name, @JsonProperty("value") final double value) {
+    public StoredDoubleField(@NotNull @JsonProperty("name") final String name, @NotNull @JsonProperty("value") final double value) {
         super(name);
         this.value = value;
     }
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java
index 6bddc5f0f..a93e3fade 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java
@@ -13,6 +13,8 @@
 
 package org.apache.couchdb.nouveau.api.document;
 
+import javax.validation.constraints.NotNull;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -21,7 +23,7 @@ public final class StoredStringField extends Field {
     private String value;
 
     @JsonCreator
-    public StoredStringField(@JsonProperty("name") final String name, @JsonProperty("value") final String value) {
+    public StoredStringField(@NotNull @JsonProperty("name") final String name, @NotNull @JsonProperty("value") final String value) {
         super(name);
         this.value = value;
     }
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java
index 7e7565815..d03a6f38a 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java
@@ -16,21 +16,33 @@ package org.apache.couchdb.nouveau.api.document;
 import javax.validation.constraints.NotNull;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
 
+@JsonInclude(value=Include.NON_DEFAULT)
 public final class StringField extends Field {
 
-    @NotNull
     private final String value;
 
-    private final boolean stored;
+    private final boolean store;
+
+    private final boolean facet;
+
+    private final boolean sortable;
 
     @JsonCreator
-    public StringField(@JsonProperty("name") final String name, @JsonProperty("value") final String value,
-            @JsonProperty("stored") final boolean stored) {
+    public StringField(
+        @NotNull @JsonProperty("name") final String name,
+        @NotNull @JsonProperty("value") final String value,
+        @JsonProperty("store") final boolean store,
+        @JsonProperty("facet") final boolean facet,
+        @JsonProperty("sortable") final boolean sortable) {
         super(name);
         this.value = value;
-        this.stored = stored;
+        this.store = store;
+        this.facet = facet;
+        this.sortable = sortable;
     }
 
     @JsonProperty
@@ -39,13 +51,24 @@ public final class StringField extends Field {
     }
 
     @JsonProperty
-    public boolean isStored() {
-        return stored;
+    public boolean isStore() {
+        return store;
+    }
+
+    @JsonProperty
+    public boolean isFacet() {
+        return facet;
+    }
+
+    @JsonProperty
+    public boolean isSortable() {
+        return sortable;
     }
 
     @Override
     public String toString() {
-        return "TextField [name=" + name + ", value=" + value + ", stored=" + stored + "]";
+        return "StringField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
+                + "]";
     }
 
 }
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java
index 5c0604bb5..0c8903c77 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java
+++ b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java
@@ -13,19 +13,36 @@
 
 package org.apache.couchdb.nouveau.api.document;
 
+import javax.validation.constraints.NotNull;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
 
+@JsonInclude(value=Include.NON_DEFAULT)
 public final class TextField extends Field {
 
     private final String value;
 
-    private final boolean stored;
+    private final boolean store;
+
+    private final boolean facet;
+
+    private final boolean sortable;
 
-    public TextField(@JsonProperty("name") final String name, @JsonProperty("value") final String value,
-            @JsonProperty("stored") final boolean stored) {
+    @JsonCreator
+    public TextField(
+        @NotNull @JsonProperty("name") final String name,
+        @NotNull @JsonProperty("value") final String value,
+        @JsonProperty("store") final boolean store,
+        @JsonProperty("facet") final boolean facet,
+        @JsonProperty("sortable") final boolean sortable) {
         super(name);
         this.value = value;
-        this.stored = stored;
+        this.store = store;
+        this.facet = facet;
+        this.sortable = sortable;
     }
 
     @JsonProperty
@@ -34,13 +51,24 @@ public final class TextField extends Field {
     }
 
     @JsonProperty
-    public boolean isStored() {
-        return stored;
+    public boolean isStore() {
+        return store;
+    }
+
+    @JsonProperty
+    public boolean isFacet() {
+        return facet;
+    }
+
+    @JsonProperty
+    public boolean isSortable() {
+        return sortable;
     }
 
     @Override
     public String toString() {
-        return "TextField [name=" + name + ", value=" + value + ", stored=" + stored + "]";
+        return "TextField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
+                + "]";
     }
 
 }
diff --git a/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java b/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java
index 4ee310ea5..1c79f8fe1 100644
--- a/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java
+++ b/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java
@@ -19,10 +19,11 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.couchdb.nouveau.api.document.DoublePoint;
+import org.apache.couchdb.nouveau.api.document.DoubleField;
 import org.apache.couchdb.nouveau.api.document.Field;
 import org.apache.couchdb.nouveau.api.document.StringField;
 import org.apache.couchdb.nouveau.api.document.TextField;
+
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import org.junit.jupiter.api.BeforeAll;
@@ -55,9 +56,9 @@ public class DocumentUpdateRequestTest {
 
     private DocumentUpdateRequest asObject() {
         final List<Field> fields = new ArrayList<Field>();
-        fields.add(new StringField("stringfoo", "bar", true));
-        fields.add(new TextField("textfoo", "hello there", true));
-        fields.add(new DoublePoint("doublefoo", 12));
+        fields.add(new StringField("stringfoo", "bar", true, false, false));
+        fields.add(new TextField("textfoo", "hello there", true, false, false));
+        fields.add(new DoubleField("doublefoo", 12, false, false, false));
         return new DocumentUpdateRequest(12, null, fields);
     }
 
diff --git a/java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json b/java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json
index ee2069542..a22e322d4 100644
--- a/java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json
+++ b/java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json
@@ -5,18 +5,18 @@
       "@type": "string",
       "name": "stringfoo",
       "value": "bar",
-      "stored": true
+      "store": true
     },
     {
       "@type": "text",
       "name": "textfoo",
       "value": "hello there",
-      "stored": true
+      "store": true
     },
     {
-      "@type": "double_point",
+      "@type": "double",
       "name": "doublefoo",
-      "value": [12]
+      "value": 12
     }
   ]
 }
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java
index ec3ccaa01..d6986c6ef 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java
@@ -34,11 +34,8 @@ import org.apache.couchdb.nouveau.api.DoubleRange;
 import org.apache.couchdb.nouveau.api.SearchHit;
 import org.apache.couchdb.nouveau.api.SearchRequest;
 import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.api.document.DoubleDocValuesField;
 import org.apache.couchdb.nouveau.api.document.DoubleField;
 import org.apache.couchdb.nouveau.api.document.Field;
-import org.apache.couchdb.nouveau.api.document.SortedDocValuesField;
-import org.apache.couchdb.nouveau.api.document.SortedSetDocValuesField;
 import org.apache.couchdb.nouveau.api.document.StoredDoubleField;
 import org.apache.couchdb.nouveau.api.document.StoredStringField;
 import org.apache.couchdb.nouveau.api.document.StringField;
@@ -323,12 +320,13 @@ class Lucene4Index extends Index {
         final Document result = new Document();
 
         // id
-        result.add(new org.apache.lucene.document.StringField("_id", docId, Store.YES));
-        result.add(new org.apache.lucene.document.SortedDocValuesField("_id", new BytesRef(docId)));
+        addIndexableFields(result,
+                new StringField("_id", docId, true, false, true));
 
         // partition (optional)
         if (request.hasPartition()) {
-            result.add(new org.apache.lucene.document.StringField("_partition", request.getPartition(), Store.NO));
+            addIndexableFields(result,
+                    new StringField("_partition", request.getPartition(), false, false, false));
         }
 
         for (Field field : request.getFields()) {
@@ -336,48 +334,35 @@ class Lucene4Index extends Index {
             if (field.getName().startsWith("_")) {
                 continue;
             }
-            result.add(toIndexableField(field));
+            addIndexableFields(result, field);
         }
 
         return result;
     }
 
-    private static IndexableField toIndexableField(final Field field) {
-        if (field instanceof DoubleDocValuesField) {
-            final DoubleDocValuesField f = (DoubleDocValuesField) field;
-            return new org.apache.lucene.document.DoubleDocValuesField(f.getName(), f.getValue());
-        }
+    private static void addIndexableFields(final Document doc, final Field field) {
         if (field instanceof DoubleField) {
             final DoubleField f = (DoubleField) field;
-            return new org.apache.lucene.document.DoubleField(f.getName(), f.getValue(), f.isStored() ? Store.YES : Store.NO);
-        }
-        if (field instanceof SortedDocValuesField) {
-            final SortedDocValuesField f = (SortedDocValuesField) field;
-            return new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue()));
-        }
-        if (field instanceof SortedSetDocValuesField) {
-            final SortedSetDocValuesField f = (SortedSetDocValuesField) field;
-            return new org.apache.lucene.document.SortedSetDocValuesField(f.getName(), new BytesRef(f.getValue()));
-        }
-        if (field instanceof StoredDoubleField) {
-            final StoredDoubleField f = (StoredDoubleField) field;
-            return new org.apache.lucene.document.StoredField(f.getName(), f.getValue());
-        }
-        if (field instanceof StoredStringField) {
-            final StoredStringField f = (StoredStringField) field;
-            return new org.apache.lucene.document.StoredField(f.getName(), f.getValue());
-        }
-        if (field instanceof StringField) {
-            final StringField f = (StringField) field;
-            return new org.apache.lucene.document.StringField(f.getName(), f.getValue(),
-                f.isStored() ? Store.YES : Store.NO);
-        }
-        if (field instanceof TextField) {
+            doc.add(new org.apache.lucene.document.DoubleField(f.getName(), f.getValue(), f.isStore() ? Store.YES : Store.NO));
+            if (f.isFacet()) {
+                doc.add(new org.apache.lucene.document.DoubleDocValuesField(f.getName(), f.getValue()));
+            }
+        } else if (field instanceof StringField) {
             final StringField f = (StringField) field;
-            return new org.apache.lucene.document.TextField(f.getName(), f.getValue(),
-                f.isStored() ? Store.YES : Store.NO);
+            doc.add(new org.apache.lucene.document.StringField(f.getName(), f.getValue(),
+                    f.isStore() ? Store.YES : Store.NO));
+            if (f.isSortable() || f.isFacet()) {
+                doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
+            }
+        } else if (field instanceof TextField) {
+            final TextField f = (TextField) field;
+            doc.add(new org.apache.lucene.document.TextField(f.getName(), f.getValue(), f.isStore() ? Store.YES : Store.NO));
+            if (f.isSortable() || f.isFacet()) {
+                doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
+            }
+        } else {
+            throw new WebApplicationException(field.getClass() + " is not valid", Status.BAD_REQUEST);
         }
-        throw new WebApplicationException(field.getClass() + " is not valid", Status.BAD_REQUEST);
     }
 
     private static Field toField(final IndexableField field) {
diff --git a/java/nouveau/lucene9/src/main/java/org/apache/couchdb/nouveau/core/lucene9/Lucene9Index.java b/java/nouveau/lucene9/src/main/java/org/apache/couchdb/nouveau/core/lucene9/Lucene9Index.java
index 79b801032..705fbac11 100644
--- a/java/nouveau/lucene9/src/main/java/org/apache/couchdb/nouveau/core/lucene9/Lucene9Index.java
+++ b/java/nouveau/lucene9/src/main/java/org/apache/couchdb/nouveau/core/lucene9/Lucene9Index.java
@@ -34,12 +34,8 @@ import org.apache.couchdb.nouveau.api.DoubleRange;
 import org.apache.couchdb.nouveau.api.SearchHit;
 import org.apache.couchdb.nouveau.api.SearchRequest;
 import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.api.document.DoubleDocValuesField;
 import org.apache.couchdb.nouveau.api.document.DoubleField;
-import org.apache.couchdb.nouveau.api.document.DoublePoint;
 import org.apache.couchdb.nouveau.api.document.Field;
-import org.apache.couchdb.nouveau.api.document.SortedDocValuesField;
-import org.apache.couchdb.nouveau.api.document.SortedSetDocValuesField;
 import org.apache.couchdb.nouveau.api.document.StoredDoubleField;
 import org.apache.couchdb.nouveau.api.document.StoredStringField;
 import org.apache.couchdb.nouveau.api.document.StringField;
@@ -314,12 +310,13 @@ class Lucene9Index extends Index {
         final Document result = new Document();
 
         // id
-        result.add(new org.apache.lucene.document.StringField("_id", docId, Store.YES));
-        result.add(new org.apache.lucene.document.SortedDocValuesField("_id", new BytesRef(docId)));
+        addIndexableFields(result,
+            new StringField("_id", docId, true, false, true));
 
         // partition (optional)
         if (request.hasPartition()) {
-            result.add(new org.apache.lucene.document.StringField("_partition", request.getPartition(), Store.NO));
+            addIndexableFields(result,
+                new StringField("_partition", request.getPartition(), false, false, false));
         }
 
         for (Field field : request.getFields()) {
@@ -334,47 +331,40 @@ class Lucene9Index extends Index {
     }
 
     private static void addIndexableFields(final Document doc, final Field field) {
-        if (field instanceof DoubleDocValuesField) {
-            final DoubleDocValuesField f = (DoubleDocValuesField) field;
-            doc.add(new org.apache.lucene.document.DoubleDocValuesField(f.getName(), f.getValue()));
-            return;
-        } else if (field instanceof DoubleField) {
+        if (field instanceof DoubleField) {
             final DoubleField f = (DoubleField) field;
-            doc.add(new org.apache.lucene.document.DoubleField(f.getName(), f.getValue()));
-            if (f.isStored()) {
+            if (f.isSortable() && f.isFacet()) {
+                doc.add(new org.apache.lucene.document.DoubleField(f.getName(), f.getValue()));
+            } else {
+                if (f.isSortable()) {
+                    doc.add(new org.apache.lucene.document.DoublePoint(f.getName(), f.getValue()));
+                }
+                if (f.isFacet()) {
+                    doc.add(new org.apache.lucene.document.DoubleDocValuesField(f.getName(), f.getValue()));
+                }
+            }
+            if (f.isStore()) {
                 doc.add(new org.apache.lucene.document.StoredField(f.getName(), f.getValue()));
             }
-            return;
-        } else if (field instanceof DoublePoint) {
-            final DoublePoint f = (DoublePoint) field;
-            doc.add(new org.apache.lucene.document.DoublePoint(f.getName(), f.getValue()));
-            return;
-        } else if (field instanceof SortedDocValuesField) {
-            final SortedDocValuesField f = (SortedDocValuesField) field;
-            doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
-            return;
-        } else if (field instanceof SortedSetDocValuesField) {
-            final SortedSetDocValuesField f = (SortedSetDocValuesField) field;
-            doc.add(new org.apache.lucene.document.SortedSetDocValuesField(f.getName(), new BytesRef(f.getValue())));
-            return;
-        } else if (field instanceof StoredDoubleField) {
-            final StoredDoubleField f = (StoredDoubleField) field;
-            doc.add(new org.apache.lucene.document.StoredField(f.getName(), f.getValue()));
-            return;
-        } else if (field instanceof StoredStringField) {
-            final StoredStringField f = (StoredStringField) field;
-            doc.add(new org.apache.lucene.document.StoredField(f.getName(), f.getValue()));
-            return;
         } else if (field instanceof StringField) {
             final StringField f = (StringField) field;
             doc.add(new org.apache.lucene.document.StringField(f.getName(), f.getValue(),
-                f.isStored() ? Store.YES : Store.NO));
-            return;
+                    f.isStore() ? Store.YES : Store.NO));
+            if (f.isSortable() || f.isFacet()) {
+                doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
+            }
+            if (f.isStore()) {
+                doc.add(new org.apache.lucene.document.StoredField(f.getName(), f.getValue()));
+            }
         } else if (field instanceof TextField) {
-            final StringField f = (StringField) field;
-            doc.add(new org.apache.lucene.document.TextField(f.getName(), f.getValue(),
-                f.isStored() ? Store.YES : Store.NO));
-            return;
+            final TextField f = (TextField) field;
+            doc.add(new org.apache.lucene.document.TextField(f.getName(), f.getValue(), f.isStore() ? Store.YES : Store.NO));
+            if (f.isSortable() || f.isFacet()) {
+                doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
+            }
+            if (f.isStore()) {
+                doc.add(new org.apache.lucene.document.StoredField(f.getName(), f.getValue()));
+            }
         } else {
             throw new WebApplicationException(field.getClass() + " is not valid", Status.BAD_REQUEST);
         }
diff --git a/java/nouveau/server/README.md b/java/nouveau/server/README.md
index cd56a8de3..696932ba9 100644
--- a/java/nouveau/server/README.md
+++ b/java/nouveau/server/README.md
@@ -98,8 +98,6 @@ To ease migration nouveau functions can use the 'index' function exactly as it e
 | index("foo", "bar");                               | adds a TextField.
 | index("foo", "bar", {"store":true});               | adds a TextField and a StoredField.
 | index("foo", "bar", {"store":true, "facet":true}); | adds a TextField, a StoredField and a SortedSetDocValuesField.
-| index("foo", "bar", "text");                       | adds a TextField.
-| index("foo", "bar", "string");                     | adds a StringField.
-| index("foo", "bar", "stored_string");              | adds a StoredField.
-| index("foo", "bar", "sorted_set_dv");              | adds a SortedSetDocValuesField.
-| index("foo", "bar", "string", true);               | adds a TextField with Store.YES
+| index("text", "foo", "bar");                       | adds a TextField.
+| index("text", "foo", "bar", {"store":true});       | adds a TextField with Store.YES
+| index("string", "foo", "bar");                     | adds a StringField.
diff --git a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java
index d38f04525..fd82d240b 100644
--- a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java
+++ b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java
@@ -32,9 +32,8 @@ import org.apache.couchdb.nouveau.api.DoubleRange;
 import org.apache.couchdb.nouveau.api.IndexDefinition;
 import org.apache.couchdb.nouveau.api.SearchRequest;
 import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.api.document.DoubleDocValuesField;
-import org.apache.couchdb.nouveau.api.document.DoublePoint;
-import org.apache.couchdb.nouveau.api.document.SortedSetDocValuesField;
+import org.apache.couchdb.nouveau.api.document.DoubleField;
+import org.apache.couchdb.nouveau.api.document.StringField;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
@@ -93,9 +92,9 @@ public class IntegrationTest {
         for (int i = 0; i < 10; i++) {
             final DocumentUpdateRequest docUpdate = new DocumentUpdateRequest(i + 1, null,
                 List.of(
-                    new DoublePoint("foo", i),
-                    new DoubleDocValuesField("baz", i),
-                    new SortedSetDocValuesField("bar", new byte[]{'b', 'a', 'z'})));
+                    new DoubleField("foo", i, false, false, false),
+                    new DoubleField("baz", i, false, true, false),
+                    new StringField("bar", "baz", false, true, false)));
             response =
                 APP.client().target(String.format("%s/index/%s/doc/doc%d", url, indexName, i))
                 .request()
diff --git a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java
index b383f123d..c45cdb758 100644
--- a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java
+++ b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java
@@ -19,7 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 
 import org.apache.couchdb.nouveau.api.After;
 import org.apache.couchdb.nouveau.api.DoubleRange;
-import org.apache.couchdb.nouveau.api.document.DoublePoint;
+import org.apache.couchdb.nouveau.api.document.DoubleField;
 import org.apache.couchdb.nouveau.api.document.StoredDoubleField;
 import org.apache.couchdb.nouveau.api.document.StoredStringField;
 import org.apache.couchdb.nouveau.api.document.StringField;
@@ -40,53 +40,45 @@ public class SerializationTest {
 
     @Test
     public void testSerializeStringFieldStoreYES() throws Exception {
-        final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\",\"stored\":true}";
-        final String actual = mapper.writeValueAsString(new StringField("foo", "bar", true));
+        final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\",\"store\":true}";
+        final String actual = mapper.writeValueAsString(new StringField("foo", "bar", true, false, false));
         assertEquals(expected, actual);
     }
 
     @Test
     public void testSerializeStringFieldStoreNO() throws Exception {
-        final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\",\"stored\":false}";
-        final String actual = mapper.writeValueAsString(new StringField("foo", "bar", false));
+        final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\"}";
+        final String actual = mapper.writeValueAsString(new StringField("foo", "bar", false, false, false));
         assertEquals(expected, actual);
     }
 
     @Test
     public void testSerializeTextFieldStoreYES() throws Exception {
-        final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\",\"stored\":true}";
-        final String actual = mapper.writeValueAsString(new TextField("foo", "bar", true));
+        final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\",\"store\":true}";
+        final String actual = mapper.writeValueAsString(new TextField("foo", "bar", true, false, false));
         assertEquals(expected, actual);
     }
 
     @Test
     public void testSerializeTextFieldStoreNO() throws Exception {
-        final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\",\"stored\":false}";
-        final String actual = mapper.writeValueAsString(new TextField("foo", "bar", false));
+        final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\"}";
+        final String actual = mapper.writeValueAsString(new TextField("foo", "bar", false, false, false));
         assertEquals(expected, actual);
     }
 
     @Test
-    public void testSerializeDoublePoint() throws Exception {
-        final String expected = "{\"@type\":\"double_point\",\"name\":\"foo\",\"value\":[12.5]}";
-        final String actual = mapper.writeValueAsString(new DoublePoint("foo", 12.5));
+    public void testSerializeDoubleField() throws Exception {
+        final String expected = "{\"@type\":\"double\",\"name\":\"foo\",\"value\":12.5}";
+        final String actual = mapper.writeValueAsString(new DoubleField("foo", 12.5, false, false, false));
         assertEquals(expected, actual);
     }
 
     @Test
-    public void testDeserializeDoublePoint1D() throws Exception {
-        final String json = "{\"@type\":\"double_point\",\"name\":\"foo\",\"value\":[12.5]}";
-        final DoublePoint point = mapper.readValue(json, DoublePoint.class);
-        assertEquals("foo", point.getName());
-        assertArrayEquals(new double[]{12.5}, point.getValue());
-    }
-
-    @Test
-    public void testDeserializeDoublePoint2D() throws Exception {
-        final String json = "{\"@type\":\"double_point\",\"name\":\"foo\",\"value\":[12.5,13.6]}";
-        final DoublePoint point = mapper.readValue(json, DoublePoint.class);
-        assertEquals("foo", point.getName());
-        assertArrayEquals(new double[]{12.5, 13.6}, point.getValue());
+    public void testDeserializeDoubleField1D() throws Exception {
+        final String json = "{\"@type\":\"double\",\"name\":\"foo\",\"value\":12.5}";
+        final DoubleField field = mapper.readValue(json, DoubleField.class);
+        assertEquals("foo", field.getName());
+        assertEquals(12.5, field.getValue());
     }
 
     @Test
diff --git a/share/server/nouveau.js b/share/server/nouveau.js
index 90e7ac9a9..9f9834164 100644
--- a/share/server/nouveau.js
+++ b/share/server/nouveau.js
@@ -32,78 +32,67 @@ var Nouveau = (function() {
   };
 
   return {
-    index: function(name, value) {
-      assertType('name', 'string', name);
-
-      if (name.substring(0, 1) === '_') {
-        throw({name: 'ReservedName', message: 'name must not start with an underscore'});
-      }
+    index: function() {
 
       // Dreyfus compatibility.
       if (arguments.length == 2 || (arguments.length == 3 && typeof arguments[2] == 'object')) {
-        options = arguments[2] || {};
+
+        var name = arguments[0];
+        var value = arguments[1];
+        var options = arguments[2] || {};
+
+        assertType('name', 'string', name);
+
+        if (name.substring(0, 1) === '_') {
+          throw({name: 'ReservedName', message: 'name must not start with an underscore'});
+        }
+
         if (typeof value == 'boolean') {
           // coerce to string as handling is the same.
           value = value ? 'true' : 'false'
         }
-        switch (typeof value) {
-        case 'string':
-          index_results.push({'@type': 'text', 'name': name, 'value': value, 'stored': options.store || false});
-          index_results.push({'@type': 'sorted_dv', 'name': name, 'value': value}); // for sorting.
-          if (options.facet) {
-            index_results.push({'@type': 'sorted_set_dv', 'name': name, 'value': value});
-          }
-          break;
-        case 'number':
-          index_results.push({'@type': 'double_point', 'name': name, 'value': [value]});
-          if (options.store) {
-            index_results.push({'@type': 'stored_double', 'name': name, 'value': value});
-          }
-          if (options.facet) {
-            index_results.push({'@type': 'double_dv', 'name': name, 'value': value});
-          }
-          break;
-        default:
+
+        if (!(typeof value == 'string' || typeof value == 'number')) {
           throw({name: 'TypeError', message: 'value must be a string, a number or boolean not ' + typeof value});
         }
-        return;
-      }
 
-      var type = arguments[2];
-      assertType('type', 'string', type);
-
-      switch (type) {
-      case 'sorted_set_dv':
-      case 'sorted_dv':
-        assertType('value', 'string', value);
-        index_results.push({'@type': type, 'name': name, 'value': value});
-        break;
-      case 'double_point':
-        assertType('value', 'number', value);
-        index_results.push({'@type': type, 'name': name, 'value': [value]});
-        break;
-      case 'double_dv':
-        assertType('value', 'number', value);
-        index_results.push({'@type': type, 'name': name, 'value': value});
-        break;
-      case 'string':
-      case 'text':
-        assertType('value', 'string', value);
-        if (arguments.length === 4) {
-          assertType('boolean', arguments[3]);
+        index_results.push({
+          '@type': typeof value == 'string' ? 'string' : 'double',
+          'name': name,
+          'value': value,
+          'store': options.store|| false,
+          'facet': options.facet|| false
+        });
+      } else { // nouveau api
+        var type = arguments[0];
+        var name = arguments[1];
+
+        assertType('type', 'string', type);
+        assertType('name', 'string', name);
+
+        if (name.substring(0, 1) === '_') {
+          throw({name: 'ReservedName', message: 'name must not start with an underscore'});
+        }
+
+        switch (type) {
+        case 'double':
+        case 'string':
+        case 'text':
+          var value = arguments[2];
+          var options = arguments[3];
+          assertType('value', type == 'double' ? 'number' : 'string', value);
+          index_results.push({
+            '@type': type,
+            'name': name,
+            'value': value,
+            'store': options.store|| false
+            'facet': options.facet|| false,
+            'sortable': options.sortable|| true
+          });
+          break;
+        default:
+          throw({name: 'TypeError', message: type + ' not supported'});
         }
-        index_results.push({'@type': type, 'name': name, 'value': value, 'stored': arguments[3] || false});
-        break;
-      case 'stored_double':
-        assertType('value', 'number', value);
-        index_results.push({'@type': type, 'name': name, 'value': value});
-        break;
-      case 'stored_string':
-        assertType('value', 'string', value);
-        index_results.push({'@type': type, 'name': name, 'value': value});
-        break;
-      default:
-        throw({name: 'TypeError', message: type + ' not supported'});
       }
     },
 
diff --git a/src/mango/src/mango_native_proc.erl b/src/mango/src/mango_native_proc.erl
index 5b0600021..de7431c6e 100644
--- a/src/mango/src/mango_native_proc.erl
+++ b/src/mango/src/mango_native_proc.erl
@@ -351,8 +351,7 @@ convert_to_nouveau_string_field([Name, Value, []]) when is_binary(Name), is_bina
     {[
         {<<"@type">>, <<"string">>},
         {<<"name">>, Name},
-        {<<"value">>, Value},
-        {<<"stored">>, false}
+        {<<"value">>, Value}
     ]}.
 
 convert_nouveau_fields([]) ->
@@ -362,24 +361,17 @@ convert_nouveau_fields([{Name, <<"string">>, Value} | Rest]) ->
         {[
             {<<"@type">>, <<"text">>},
             {<<"name">>, Name},
-            {<<"value">>, Value},
-            {<<"stored">>, false}
+            {<<"value">>, Value}
         ]},
     [Field | convert_nouveau_fields(Rest)];
 convert_nouveau_fields([{Name, <<"number">>, Value} | Rest]) ->
-    PointField =
-        {[
-            {<<"@type">>, <<"double_point">>},
-            {<<"name">>, Name},
-            {<<"value">>, Value}
-        ]},
-    DocValuesField =
+    Field =
         {[
-            {<<"@type">>, <<"double_dv">>},
+            {<<"@type">>, <<"double">},
             {<<"name">>, Name},
             {<<"value">>, Value}
         ]},
-    [PointField, DocValuesField | convert_nouveau_fields(Rest)];
+    [Field | convert_nouveau_fields(Rest)];
 convert_nouveau_fields([{Name, <<"boolean">>, true} | Rest]) ->
     Field =
         {[