blob: 12199544923941f0af6bc59491822695a39c6d00 [file] [log] [blame]
defmodule PartitionSearchTest do
use CouchTestCase
@moduletag :search
@moduledoc """
Test Partition functionality with search
"""
def create_search_docs(db_name, pk1 \\ "foo", pk2 \\ "bar") do
docs = for i <- 1..10 do
id = if rem(i, 2) == 0 do
"#{pk1}:#{i}"
else
"#{pk2}:#{i}"
end
%{
:_id => id,
:value => i,
:some => "field"
}
end
resp = Couch.post("/#{db_name}/_bulk_docs", headers: ["Content-Type": "application/json"], body: %{:docs => docs}, query: %{w: 3})
assert resp.status_code in [201, 202]
end
def create_ddoc(db_name, opts \\ %{}) do
index_fn = "function(doc) {\n if (doc.some) {\n index('some', doc.some);\n }\n}"
default_ddoc = %{
indexes: %{
books: %{
analyzer: %{name: "standard"},
index: index_fn
}
}
}
ddoc = Enum.into(opts, default_ddoc)
resp = Couch.put("/#{db_name}/_design/library", body: ddoc)
assert resp.status_code in [201, 202]
assert Map.has_key?(resp.body, "ok") == true
end
def get_ids (resp) do
%{:body => %{"rows" => rows}} = resp
Enum.map(rows, fn row -> row["id"] end)
end
@tag :with_partitioned_db
test "Simple query returns partitioned search results", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:10", "foo:2", "foo:4", "foo:6", "foo:8"]
url = "/#{db_name}/_partition/bar/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["bar:1", "bar:3", "bar:5", "bar:7", "bar:9"]
end
@tag :with_partitioned_db
test "Only returns docs in partition not those in shard", context do
db_name = context[:db_name]
create_search_docs(db_name, "foo", "bar42")
create_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:10", "foo:2", "foo:4", "foo:6", "foo:8"]
end
@tag :with_partitioned_db
test "Works with bookmarks and limit", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field", limit: 3})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:10", "foo:2", "foo:4"]
%{:body => %{"bookmark" => bookmark}} = resp
resp = Couch.get(url, query: %{q: "some:field", limit: 3, bookmark: bookmark})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:6", "foo:8"]
resp = Couch.get(url, query: %{q: "some:field", limit: 2000, bookmark: bookmark})
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:6", "foo:8"]
resp = Couch.get(url, query: %{q: "some:field", limit: 2001, bookmark: bookmark})
assert resp.status_code == 400
end
@tag :with_db
test "Works with limit using POST for on non-partitioned db", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.post(url, body: %{:q => "some:field", :limit => 1})
assert resp.status_code == 200
end
@tag :with_partitioned_db
test "Works with limit using POST for partitioned db", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.post(url, body: %{:q => "some:field", :limit => 1})
assert resp.status_code == 200
end
@tag :with_partitioned_db
test "Cannot do global query with partition view", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 400
%{:body => %{"reason" => reason}} = resp
assert Regex.match?(~r/mandatory for queries to this index./, reason)
end
@tag :with_partitioned_db
test "Cannot do partition query with global search ddoc", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name, options: %{partitioned: false})
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 400
%{:body => %{"reason" => reason}} = resp
assert reason == "`partition` not supported on this index"
end
@tag :with_db
test "normal search on non-partitioned dbs still work", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"])
end
@tag :with_db
test "normal search on non-partitioned dbs without limit", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"])
end
@tag :with_db
test "normal search on non-partitioned dbs with limit", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field", limit: 3})
assert resp.status_code == 200
ids = get_ids(resp)
assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9"])
end
@tag :with_db
test "normal search on non-partitioned dbs with over limit", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_design/library/_search/books"
resp = Couch.get(url, query: %{q: "some:field", limit: 201})
assert resp.status_code == 400
end
@tag :with_partitioned_db
test "rejects conflicting partition values", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
resp = Couch.post(url, body: %{q: "some:field", partition: "bar"})
assert resp.status_code == 400
end
@tag :with_partitioned_db
test "restricted parameters are not allowed in query or body", context do
db_name = context[:db_name]
create_search_docs(db_name)
create_ddoc(db_name)
body = %{q: "some:field", partition: "foo"}
Enum.each(
[
{:counts, "[\"type\"]"},
{:group_field, "some"},
{:ranges, :jiffy.encode(%{price: %{cheap: "[0 TO 100]"}})},
{:drilldown, "[\"key\",\"a\"]"},
],
fn {key, value} ->
url = "/#{db_name}/_partition/foo/_design/library/_search/books"
bannedparam = Map.put(body, key, value)
get_resp = Couch.get(url, query: bannedparam)
%{:body => %{"reason" => get_reason}} = get_resp
assert Regex.match?(~r/are incompatible/, get_reason)
post_resp = Couch.post(url, body: bannedparam)
%{:body => %{"reason" => post_reason}} = post_resp
assert Regex.match?(~r/are incompatible/, post_reason)
end
)
end
end