summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mango/src/mango_cursor_view.erl19
-rw-r--r--src/mango/test/22-covering-index-test.py92
-rw-r--r--src/mango/test/mango.py27
-rw-r--r--src/mango/test/user_docs.py15
4 files changed, 125 insertions, 28 deletions
diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl
index e044c56fc..82b4008bb 100644
--- a/src/mango/src/mango_cursor_view.erl
+++ b/src/mango/src/mango_cursor_view.erl
@@ -435,7 +435,12 @@ match_and_extract_doc(Doc, Selector, Fields) ->
end.
-spec derive_doc_from_index(#idx{}, #view_row{}) -> term().
-derive_doc_from_index(Index, #view_row{id = DocId, key = Keys}) ->
+derive_doc_from_index(Index, #view_row{id = DocId, key = KeyData}) ->
+ Keys =
+ case KeyData of
+ {p, _Partition, KeyValues} -> KeyValues;
+ KeyValues -> KeyValues
+ end,
Columns = mango_idx:columns(Index),
lists:foldr(
fun({Column, Key}, Doc) -> mango_doc:set_field(Doc, Column, Key) end,
@@ -862,6 +867,18 @@ derive_doc_from_index_test() ->
Doc = {[{<<"_id">>, DocId}, {<<"field2">>, key2}, {<<"field1">>, key1}]},
?assertEqual(Doc, derive_doc_from_index(Index, ViewRow)).
+derive_doc_from_index_partitioned_test() ->
+ Index =
+ #idx{
+ type = <<"json">>,
+ def = {[{<<"fields">>, {[{<<"field1">>, undefined}, {<<"field2">>, undefined}]}}]}
+ },
+ DocId = doc_id,
+ Keys = [key1, key2],
+ ViewRow = #view_row{id = DocId, key = {p, partition, Keys}},
+ Doc = {[{<<"_id">>, DocId}, {<<"field2">>, key2}, {<<"field1">>, key1}]},
+ ?assertEqual(Doc, derive_doc_from_index(Index, ViewRow)).
+
composite_indexes_test() ->
?assertEqual([], composite_indexes([], [])),
Index1 =
diff --git a/src/mango/test/22-covering-index-test.py b/src/mango/test/22-covering-index-test.py
index 52a7f3612..176dd2d81 100644
--- a/src/mango/test/22-covering-index-test.py
+++ b/src/mango/test/22-covering-index-test.py
@@ -13,19 +13,7 @@
import mango
-class CoveringIndexTests(mango.UserDocsTests):
- def is_covered(self, selector, fields, index, use_index=None):
- resp = self.db.find(selector, fields=fields, use_index=use_index, explain=True)
- self.assertEqual(resp["index"]["type"], "json")
- self.assertEqual(resp["index"]["name"], index)
- self.assertEqual(resp["mrargs"]["include_docs"], False)
- self.assertEqual(resp["covered"], True)
-
- def is_not_covered(self, selector, fields, use_index=None):
- resp = self.db.find(selector, fields=fields, use_index=use_index, explain=True)
- self.assertEqual(resp["mrargs"]["include_docs"], True)
- self.assertEqual(resp["covered"], False)
-
+class CoveringIndexTests:
def test_index_covers_query_1field_index_id(self):
self.is_covered({"age": {"$gte": 32}}, ["_id"], "age")
@@ -88,6 +76,45 @@ class CoveringIndexTests(mango.UserDocsTests):
use_index="twitter",
)
+
+class RegularCoveringIndexTests(mango.UserDocsTests, CoveringIndexTests):
+ @classmethod
+ def setUpClass(klass):
+ super(RegularCoveringIndexTests, klass).setUpClass()
+
+ def is_covered(self, selector, fields, index, use_index=None):
+ resp = self.db.find(selector, fields=fields, use_index=use_index, explain=True)
+ self.assertEqual(resp["index"]["type"], "json")
+ self.assertEqual(resp["index"]["name"], index)
+ self.assertEqual(resp["mrargs"]["include_docs"], False)
+ self.assertEqual(resp["covered"], True)
+
+ def is_not_covered(self, selector, fields, use_index=None):
+ resp = self.db.find(selector, fields=fields, use_index=use_index, explain=True)
+ self.assertEqual(resp["mrargs"]["include_docs"], True)
+ self.assertEqual(resp["covered"], False)
+
+ def test_covering_index_provides_correct_answer_2field_index(self):
+ docs = self.db.find(
+ {"company": {"$exists": True}, "manager": True},
+ sort=[{"company": "asc"}],
+ fields=["company"],
+ use_index="company_and_manager",
+ )
+ expected = [
+ {"company": "Affluex"},
+ {"company": "Globoil"},
+ {"company": "Lyria"},
+ {"company": "Manglo"},
+ {"company": "Myopium"},
+ {"company": "Niquent"},
+ {"company": "Oulu"},
+ {"company": "Prosely"},
+ {"company": "Tasmania"},
+ {"company": "Zialactic"},
+ ]
+ self.assertEqual(docs, expected)
+
def test_covering_index_provides_correct_answer_id(self):
docs = self.db.find({"age": {"$gte": 32}}, fields=["_id"])
expected = [
@@ -107,23 +134,50 @@ class CoveringIndexTests(mango.UserDocsTests):
]
self.assertEqual(docs, expected)
+
+class PartitionedCoveringIndexTests(mango.PartitionedUserDocsTests, CoveringIndexTests):
+ @classmethod
+ def setUpClass(klass):
+ super(PartitionedCoveringIndexTests, klass).setUpClass()
+
+ def is_covered(self, selector, fields, index, use_index=None):
+ resp = self.db.find(
+ selector, fields=fields, use_index=use_index, explain=True, partition="0"
+ )
+ self.assertEqual(resp["index"]["type"], "json")
+ self.assertEqual(resp["index"]["name"], index)
+ self.assertEqual(resp["mrargs"]["include_docs"], False)
+ self.assertEqual(resp["covered"], True)
+
+ def is_not_covered(self, selector, fields, use_index=None):
+ resp = self.db.find(
+ selector, fields=fields, use_index=use_index, explain=True, partition="0"
+ )
+ self.assertEqual(resp["mrargs"]["include_docs"], True)
+ self.assertEqual(resp["covered"], False)
+
def test_covering_index_provides_correct_answer_2field_index(self):
docs = self.db.find(
{"company": {"$exists": True}, "manager": True},
sort=[{"company": "asc"}],
fields=["company"],
use_index="company_and_manager",
+ partition="0",
)
expected = [
- {"company": "Affluex"},
- {"company": "Globoil"},
- {"company": "Lyria"},
{"company": "Manglo"},
- {"company": "Myopium"},
- {"company": "Niquent"},
{"company": "Oulu"},
{"company": "Prosely"},
{"company": "Tasmania"},
- {"company": "Zialactic"},
]
self.assertEqual(docs, expected)
+
+ def test_covering_index_provides_correct_answer_id(self):
+ docs = self.db.find({"age": {"$gte": 32}}, fields=["_id"], partition="0")
+ expected = [
+ {"_id": "0:0461444c-e60a-457d-a4bb-b8d811853f21"},
+ {"_id": "0:5b61abc1-a3d3-4092-b9d7-ced90e675536"},
+ {"_id": "0:71562648-6acb-42bc-a182-df6b1f005b09"},
+ {"_id": "0:b31dad3f-ae8b-4f86-8327-dfe8770beb27"},
+ ]
+ self.assertEqual(sorted(docs, key=lambda x: x["_id"]), expected)
diff --git a/src/mango/test/mango.py b/src/mango/test/mango.py
index 81bc082b6..20a40d1b7 100644
--- a/src/mango/test/mango.py
+++ b/src/mango/test/mango.py
@@ -66,10 +66,11 @@ class Database(object):
parts = [parts]
return "/".join([self.url] + parts)
- def create(self, q=1, n=1):
+ def create(self, q=1, n=1, partitioned=False):
r = self.sess.get(self.url)
if r.status_code == 404:
- r = self.sess.put(self.url, params={"q": q, "n": n})
+ p = str(partitioned).lower()
+ r = self.sess.put(self.url, params={"q": q, "n": n, "partitioned": p})
r.raise_for_status()
def delete(self):
@@ -240,6 +241,7 @@ class Database(object):
return_raw=False,
update=True,
executionStats=False,
+ partition=None,
):
body = {
"selector": selector,
@@ -260,10 +262,14 @@ class Database(object):
if executionStats == True:
body["execution_stats"] = True
body = json.dumps(body)
+ if partition:
+ ppath = "_partition/{}/".format(partition)
+ else:
+ ppath = ""
if explain:
- path = self.path("_explain")
+ path = self.path("{}_explain".format(ppath))
else:
- path = self.path("_find")
+ path = self.path("{}_find".format(ppath))
r = self.sess.post(path, data=body)
r.raise_for_status()
if explain or return_raw:
@@ -298,9 +304,9 @@ class UsersDbTests(unittest.TestCase):
class DbPerClass(unittest.TestCase):
@classmethod
- def setUpClass(klass):
+ def setUpClass(klass, partitioned=False):
klass.db = Database(random_db_name())
- klass.db.create(q=1, n=1)
+ klass.db.create(q=1, n=1, partitioned=partitioned)
@classmethod
def tearDownClass(klass):
@@ -320,6 +326,15 @@ class UserDocsTests(DbPerClass):
user_docs.setup(klass.db)
+class PartitionedUserDocsTests(DbPerClass):
+ INDEX_TYPE = "json"
+
+ @classmethod
+ def setUpClass(klass):
+ super(PartitionedUserDocsTests, klass).setUpClass(partitioned=True)
+ user_docs.setup(klass.db, partitioned=True)
+
+
class UserDocsTestsNoIndexes(DbPerClass):
INDEX_TYPE = "special"
diff --git a/src/mango/test/user_docs.py b/src/mango/test/user_docs.py
index a1b6c6e1a..b2a19eea7 100644
--- a/src/mango/test/user_docs.py
+++ b/src/mango/test/user_docs.py
@@ -58,9 +58,18 @@ def setup_users(db, **kwargs):
db.save_docs(copy.deepcopy(USERS_DOCS))
-def setup(db, index_type="view", **kwargs):
+def setup(db, index_type="view", partitioned=False, **kwargs):
db.recreate()
- db.save_docs(copy.deepcopy(DOCS))
+ p = str(partitioned).lower()
+ docs = copy.deepcopy(DOCS)
+
+ if partitioned:
+ for index, doc in enumerate(docs):
+ partition = index % PARTITIONS
+ doc["_id"] = "{}:{}".format(partition, doc["_id"])
+
+ db.save_docs(docs, partitioned=p)
+
if index_type == "view":
add_view_indexes(db, kwargs)
elif index_type == "text":
@@ -96,6 +105,8 @@ def add_text_indexes(db, kwargs):
db.create_text_index(**kwargs)
+PARTITIONS = 3
+
DOCS = [
{
"_id": "71562648-6acb-42bc-a182-df6b1f005b09",