mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-23 02:27:40 +08:00
Merge #2598
2598: Bring `stable` into `main` (v0.28.0) r=curquiza a=curquiza Co-authored-by: Tamo <tamo@meilisearch.com> Co-authored-by: bors[bot] <26634292+bors[bot]@users.noreply.github.com> Co-authored-by: Kerollmops <clement@meilisearch.com> Co-authored-by: Janith Petangoda <22471198+janithpet@users.noreply.github.com> Co-authored-by: Clémentine Urquizar <clementine@meilisearch.com> Co-authored-by: Clémentine Urquizar - curqui <clementine@meilisearch.com> Co-authored-by: Irevoire <tamo@meilisearch.com> Co-authored-by: ManyTheFish <many@meilisearch.com>
This commit is contained in:
commit
01a47e2db5
28
.github/scripts/check-release.sh
vendored
Normal file
28
.github/scripts/check-release.sh
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# check_tag $current_tag $file_tag $file_name
|
||||||
|
function check_tag {
|
||||||
|
if [[ "$1" != "$2" ]]; then
|
||||||
|
echo "Error: the current tag does not match the version in $3: found $2 - expected $1"
|
||||||
|
ret=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ret=0
|
||||||
|
current_tag=${GITHUB_REF#'refs/tags/v'}
|
||||||
|
|
||||||
|
toml_files='*/Cargo.toml'
|
||||||
|
for toml_file in $toml_files;
|
||||||
|
do
|
||||||
|
file_tag="$(grep '^version = ' $toml_file | cut -d '=' -f 2 | tr -d '"' | tr -d ' ')"
|
||||||
|
check_tag $current_tag $file_tag $toml_file
|
||||||
|
done
|
||||||
|
|
||||||
|
lock_file='Cargo.lock'
|
||||||
|
lock_tag=$(grep -A 1 'name = "meilisearch-auth"' $lock_file | grep version | cut -d '=' -f 2 | tr -d '"' | tr -d ' ')
|
||||||
|
check_tag $current_tag $lock_tag $lock_file
|
||||||
|
|
||||||
|
if [[ "$ret" -eq 0 ]] ; then
|
||||||
|
echo 'OK'
|
||||||
|
fi
|
||||||
|
exit $ret
|
@ -1,14 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Checks if the current tag should be the latest (in terms of semver and not of release date).
|
# Was used in our CIs to publish the latest docker image. Not used anymore, will be used again when v1 and v2 will be out and we will want to maintain multiple stable versions.
|
||||||
# Ex: previous tag -> v0.10.1
|
|
||||||
# new tag -> v0.8.12
|
|
||||||
# The new tag should not be the latest
|
|
||||||
# So it returns "false", the CI should not run for the release v0.8.2
|
|
||||||
|
|
||||||
# Used in GHA in publish-docker-latest.yml
|
|
||||||
# Returns "true" or "false" (as a string) to be used in the `if` in GHA
|
# Returns "true" or "false" (as a string) to be used in the `if` in GHA
|
||||||
|
|
||||||
|
# Checks if the current tag should be the latest (in terms of semver and not of release date).
|
||||||
|
# Ex: previous tag -> v2.1.1
|
||||||
|
# new tag -> v1.20.3
|
||||||
|
# The new tag (v1.20.3) should NOT be the latest
|
||||||
|
# So it returns "false", the `latest` tag should not be updated for the release v1.20.3 and still need to correspond to v2.1.1
|
||||||
|
|
||||||
# GLOBAL
|
# GLOBAL
|
||||||
GREP_SEMVER_REGEXP='v\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)$' # i.e. v[number].[number].[number]
|
GREP_SEMVER_REGEXP='v\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)$' # i.e. v[number].[number].[number]
|
||||||
|
|
25
.github/workflows/publish-binaries.yml
vendored
25
.github/workflows/publish-binaries.yml
vendored
@ -5,9 +5,33 @@ on:
|
|||||||
name: Publish binaries to release
|
name: Publish binaries to release
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check-version:
|
||||||
|
name: Check the version validity
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
# Check if the tag has the v<nmumber>.<number>.<number> format.
|
||||||
|
# If yes, it means we are publishing an official release.
|
||||||
|
# If no, we are releasing a RC, so no need to check the version.
|
||||||
|
- name: Check tag format
|
||||||
|
if: github.event_name != 'schedule'
|
||||||
|
id: check-tag-format
|
||||||
|
run: |
|
||||||
|
escaped_tag=$(printf "%q" ${{ github.ref_name }})
|
||||||
|
|
||||||
|
if [[ $escaped_tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
echo ::set-output name=stable::true
|
||||||
|
else
|
||||||
|
echo ::set-output name=stable::false
|
||||||
|
fi
|
||||||
|
- name: Check release validity
|
||||||
|
if: steps.check-tag-format.outputs.stable == 'true'
|
||||||
|
run: bash .github/scripts/check-release.sh
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: Publish binary for ${{ matrix.os }}
|
name: Publish binary for ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
needs: check-version
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -41,6 +65,7 @@ jobs:
|
|||||||
publish-aarch64:
|
publish-aarch64:
|
||||||
name: Publish binary for aarch64
|
name: Publish binary for aarch64
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
needs: check-version
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
10
.github/workflows/publish-deb-brew-pkg.yml
vendored
10
.github/workflows/publish-deb-brew-pkg.yml
vendored
@ -5,9 +5,18 @@ on:
|
|||||||
types: [released]
|
types: [released]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check-version:
|
||||||
|
name: Check the version validity
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Check release validity
|
||||||
|
run: bash .github/scripts/check-release.sh
|
||||||
|
|
||||||
debian:
|
debian:
|
||||||
name: Publish debian packagge
|
name: Publish debian packagge
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-18.04
|
||||||
|
needs: check-version
|
||||||
steps:
|
steps:
|
||||||
- uses: hecrj/setup-rust-action@master
|
- uses: hecrj/setup-rust-action@master
|
||||||
with:
|
with:
|
||||||
@ -30,6 +39,7 @@ jobs:
|
|||||||
homebrew:
|
homebrew:
|
||||||
name: Bump Homebrew formula
|
name: Bump Homebrew formula
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-18.04
|
||||||
|
needs: check-version
|
||||||
steps:
|
steps:
|
||||||
- name: Create PR to Homebrew
|
- name: Create PR to Homebrew
|
||||||
uses: mislav/bump-homebrew-formula-action@v1
|
uses: mislav/bump-homebrew-formula-action@v1
|
||||||
|
47
.github/workflows/publish-docker-images.yml
vendored
47
.github/workflows/publish-docker-images.yml
vendored
@ -5,8 +5,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
release:
|
|
||||||
types: [released]
|
|
||||||
|
|
||||||
name: Publish tagged images to Docker Hub
|
name: Publish tagged images to Docker Hub
|
||||||
|
|
||||||
@ -14,45 +12,54 @@ jobs:
|
|||||||
docker:
|
docker:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Check if the tag has the v<nmumber>.<number>.<number> format. If yes, it means we are publishing an official release.
|
||||||
|
# In this situation, we need to set `output.stable` to create/update the following tags (additionally to the `vX.Y.Z` Docker tag):
|
||||||
|
# - a `vX.Y` (without patch version) Docker tag
|
||||||
|
# - a `latest` Docker tag
|
||||||
|
- name: Check tag format
|
||||||
|
if: github.event_name != 'schedule'
|
||||||
|
id: check-tag-format
|
||||||
|
run: |
|
||||||
|
escaped_tag=$(printf "%q" ${{ github.ref_name }})
|
||||||
|
|
||||||
|
if [[ $escaped_tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
echo ::set-output name=stable::true
|
||||||
|
else
|
||||||
|
echo ::set-output name=stable::false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check only the validity of the tag for official releases (not for pre-releases or other tags)
|
||||||
|
- name: Check release validity
|
||||||
|
if: github.event_name != 'schedule' && steps.check-tag-format.outputs.stable == 'true'
|
||||||
|
run: bash .github/scripts/check-release.sh
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to Docker Hub
|
||||||
if: github.event_name != 'schedule'
|
if: github.event_name != 'schedule'
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Check tag format
|
|
||||||
id: check-tag-format
|
|
||||||
run: |
|
|
||||||
# Escape submitted tag name
|
|
||||||
escaped_tag=$(printf "%q" ${{ github.ref_name }})
|
|
||||||
|
|
||||||
# Check if tag has format v<nmumber>.<number>.<number> and set output.match
|
|
||||||
# to create a vX.Y (without patch version) Docker tag
|
|
||||||
if [[ $escaped_tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo ::set-output name=match::true
|
|
||||||
else
|
|
||||||
echo ::set-output name=match::false
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: getmeili/meilisearch
|
images: getmeili/meilisearch
|
||||||
# The lastest tag is only pushed for the official Meilisearch release
|
# The lastest and `vX.Y` tags are only pushed for the official Meilisearch releases
|
||||||
# See https://github.com/docker/metadata-action#latest-tag
|
# See https://github.com/docker/metadata-action#latest-tag
|
||||||
flavor: latest=false
|
flavor: latest=false
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
type=semver,pattern=v{{major}}.{{minor}},enable=${{ steps.check-tag-format.outputs.match }}
|
type=semver,pattern=v{{major}}.{{minor}},enable=${{ steps.check-tag-format.outputs.stable == 'true' }}
|
||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
type=raw,value=latest,enable=${{ steps.check-tag-format.outputs.stable == 'true' }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
|
58
Cargo.lock
generated
58
Cargo.lock
generated
@ -1123,8 +1123,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filter-parser"
|
name = "filter-parser"
|
||||||
version = "0.29.3"
|
version = "0.31.1"
|
||||||
source = "git+https://github.com/meilisearch/milli.git?tag=v0.29.3#f1d848bb9add86b9414d110a083dfa0462d5d636"
|
source = "git+https://github.com/meilisearch/milli.git?tag=v0.31.1#83ad1aaf0552db9f63fc21ae9fe3976e61577dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nom",
|
"nom",
|
||||||
"nom_locate",
|
"nom_locate",
|
||||||
@ -1148,8 +1148,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flatten-serde-json"
|
name = "flatten-serde-json"
|
||||||
version = "0.29.3"
|
version = "0.31.1"
|
||||||
source = "git+https://github.com/meilisearch/milli.git?tag=v0.29.3#f1d848bb9add86b9414d110a083dfa0462d5d636"
|
source = "git+https://github.com/meilisearch/milli.git?tag=v0.31.1#83ad1aaf0552db9f63fc21ae9fe3976e61577dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@ -1661,8 +1661,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "json-depth-checker"
|
name = "json-depth-checker"
|
||||||
version = "0.29.3"
|
version = "0.31.1"
|
||||||
source = "git+https://github.com/meilisearch/milli.git?tag=v0.29.3#f1d848bb9add86b9414d110a083dfa0462d5d636"
|
source = "git+https://github.com/meilisearch/milli.git?tag=v0.31.1#83ad1aaf0552db9f63fc21ae9fe3976e61577dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@ -2003,7 +2003,6 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
|||||||
name = "meilisearch-auth"
|
name = "meilisearch-auth"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"hmac",
|
"hmac",
|
||||||
"meilisearch-types",
|
"meilisearch-types",
|
||||||
@ -2014,7 +2013,7 @@ dependencies = [
|
|||||||
"sha2",
|
"sha2",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
"uuid",
|
"uuid 1.1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2069,7 +2068,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde-cs",
|
"serde-cs",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_url_params",
|
|
||||||
"sha-1",
|
"sha-1",
|
||||||
"sha2",
|
"sha2",
|
||||||
"siphasher",
|
"siphasher",
|
||||||
@ -2084,9 +2082,10 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
"uuid",
|
"uuid 1.1.2",
|
||||||
"vergen",
|
"vergen",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
|
"yaup",
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2147,7 +2146,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid 1.1.2",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
@ -2189,8 +2188,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "milli"
|
name = "milli"
|
||||||
version = "0.29.3"
|
version = "0.31.1"
|
||||||
source = "git+https://github.com/meilisearch/milli.git?tag=v0.29.3#f1d848bb9add86b9414d110a083dfa0462d5d636"
|
source = "git+https://github.com/meilisearch/milli.git?tag=v0.31.1#83ad1aaf0552db9f63fc21ae9fe3976e61577dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bimap",
|
"bimap",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -2229,7 +2228,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
"uuid",
|
"uuid 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2515,7 +2514,7 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "permissive-json-pointer"
|
name = "permissive-json-pointer"
|
||||||
version = "0.2.0"
|
version = "0.28.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"big_s",
|
"big_s",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -3113,16 +3112,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_url_params"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2c43307d0640738af32fe8d01e47119bc0fc8a686be470a44a586caff76dfb34"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -3686,6 +3675,15 @@ name = "uuid"
|
|||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3994,6 +3992,16 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6d12cb7a57bbf2ab670ed9545bae3648048547f9039279a89ce000208e585c1"
|
checksum = "b6d12cb7a57bbf2ab670ed9545bae3648048547f9039279a89ce000208e585c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaup"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3bc9ef6963f7e857050aabf31ebc44184f278bcfec4c3671552c1a916b152b45"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -4,15 +4,14 @@ version = "0.28.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.13.0"
|
|
||||||
enum-iterator = "0.7.0"
|
enum-iterator = "0.7.0"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
meilisearch-types = { path = "../meilisearch-types" }
|
meilisearch-types = { path = "../meilisearch-types" }
|
||||||
milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.29.3" }
|
milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.31.1" }
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
serde = { version = "1.0.136", features = ["derive"] }
|
serde = { version = "1.0.136", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.79", features = ["preserve_order"] }
|
serde_json = { version = "1.0.79", features = ["preserve_order"] }
|
||||||
sha2 = "0.10.2"
|
sha2 = "0.10.2"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
||||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
uuid = { version = "1.1.2", features = ["serde", "v4"] }
|
||||||
|
@ -18,7 +18,7 @@ pub use action::{actions, Action};
|
|||||||
use error::{AuthControllerError, Result};
|
use error::{AuthControllerError, Result};
|
||||||
pub use key::Key;
|
pub use key::Key;
|
||||||
use meilisearch_types::star_or::StarOr;
|
use meilisearch_types::star_or::StarOr;
|
||||||
use store::generate_key_as_base64;
|
use store::generate_key_as_hexa;
|
||||||
pub use store::open_auth_store_env;
|
pub use store::open_auth_store_env;
|
||||||
use store::HeedAuthStore;
|
use store::HeedAuthStore;
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ impl AuthController {
|
|||||||
pub fn generate_key(&self, uid: Uuid) -> Option<String> {
|
pub fn generate_key(&self, uid: Uuid) -> Option<String> {
|
||||||
self.master_key
|
self.master_key
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|master_key| generate_key_as_base64(uid.as_bytes(), master_key.as_bytes()))
|
.map(|master_key| generate_key_as_hexa(uid, master_key.as_bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the provided key is authorized to make a specific action
|
/// Check if the provided key is authorized to make a specific action
|
||||||
|
@ -14,8 +14,9 @@ use hmac::{Hmac, Mac};
|
|||||||
use meilisearch_types::star_or::StarOr;
|
use meilisearch_types::star_or::StarOr;
|
||||||
use milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson};
|
use milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson};
|
||||||
use milli::heed::{Database, Env, EnvOpenOptions, RwTxn};
|
use milli::heed::{Database, Env, EnvOpenOptions, RwTxn};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::Sha256;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
use uuid::fmt::Hyphenated;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::error::Result;
|
use super::error::Result;
|
||||||
@ -169,13 +170,16 @@ impl HeedAuthStore {
|
|||||||
.remap_data_type::<DecodeIgnore>()
|
.remap_data_type::<DecodeIgnore>()
|
||||||
.iter(&rtxn)?
|
.iter(&rtxn)?
|
||||||
.filter_map(|res| match res {
|
.filter_map(|res| match res {
|
||||||
Ok((uid, _))
|
Ok((uid, _)) => {
|
||||||
if generate_key_as_base64(uid, master_key).as_bytes() == encoded_key =>
|
|
||||||
{
|
|
||||||
let (uid, _) = try_split_array_at(uid)?;
|
let (uid, _) = try_split_array_at(uid)?;
|
||||||
Some(Uuid::from_bytes(*uid))
|
let uid = Uuid::from_bytes(*uid);
|
||||||
|
if generate_key_as_hexa(uid, master_key).as_bytes() == encoded_key {
|
||||||
|
Some(uid)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
Err(_) => None,
|
||||||
})
|
})
|
||||||
.next();
|
.next();
|
||||||
|
|
||||||
@ -281,13 +285,17 @@ impl<'a> milli::heed::BytesEncode<'a> for KeyIdActionCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_key_as_base64(uid: &[u8], master_key: &[u8]) -> String {
|
pub fn generate_key_as_hexa(uid: Uuid, master_key: &[u8]) -> String {
|
||||||
let master_key_sha = Sha256::digest(master_key);
|
// format uid as hyphenated allowing user to generate their own keys.
|
||||||
let mut mac = Hmac::<Sha256>::new_from_slice(master_key_sha.as_slice()).unwrap();
|
let mut uid_buffer = [0; Hyphenated::LENGTH];
|
||||||
mac.update(uid);
|
let uid = uid.hyphenated().encode_lower(&mut uid_buffer);
|
||||||
|
|
||||||
|
// new_from_slice function never fail.
|
||||||
|
let mut mac = Hmac::<Sha256>::new_from_slice(master_key).unwrap();
|
||||||
|
mac.update(uid.as_bytes());
|
||||||
|
|
||||||
let result = mac.finalize();
|
let result = mac.finalize();
|
||||||
base64::encode_config(result.into_bytes(), base64::URL_SAFE_NO_PAD)
|
format!("{:x}", result.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Divides one slice into two at an index, returns `None` if mid is out of bounds.
|
/// Divides one slice into two at an index, returns `None` if mid is out of bounds.
|
||||||
|
@ -75,7 +75,7 @@ thiserror = "1.0.30"
|
|||||||
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
||||||
tokio = { version = "1.17.0", features = ["full"] }
|
tokio = { version = "1.17.0", features = ["full"] }
|
||||||
tokio-stream = "0.1.8"
|
tokio-stream = "0.1.8"
|
||||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
uuid = { version = "1.1.2", features = ["serde", "v4"] }
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.3.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@ -83,8 +83,8 @@ actix-rt = "2.7.0"
|
|||||||
assert-json-diff = "2.0.1"
|
assert-json-diff = "2.0.1"
|
||||||
manifest-dir-macros = "0.1.14"
|
manifest-dir-macros = "0.1.14"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
serde_url_params = "0.2.1"
|
|
||||||
urlencoding = "2.1.0"
|
urlencoding = "2.1.0"
|
||||||
|
yaup = "0.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["analytics", "mini-dashboard"]
|
default = ["analytics", "mini-dashboard"]
|
||||||
@ -105,5 +105,5 @@ mini-dashboard = [
|
|||||||
tikv-jemallocator = "0.4.3"
|
tikv-jemallocator = "0.4.3"
|
||||||
|
|
||||||
[package.metadata.mini-dashboard]
|
[package.metadata.mini-dashboard]
|
||||||
assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.1.10/build.zip"
|
assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.2.0/build.zip"
|
||||||
sha1 = "1adf96592c267425c110bfefc36b7fc6bfb0f93d"
|
sha1 = "25d1615c608541375a08bd722c3fd3315f926be6"
|
||||||
|
@ -574,7 +574,7 @@ impl DocumentsAggregator {
|
|||||||
let content_type = request
|
let content_type = request
|
||||||
.headers()
|
.headers()
|
||||||
.get(CONTENT_TYPE)
|
.get(CONTENT_TYPE)
|
||||||
.map(|s| s.to_str().unwrap_or("unknown"))
|
.and_then(|s| s.to_str().ok())
|
||||||
.unwrap_or("unknown")
|
.unwrap_or("unknown")
|
||||||
.to_string();
|
.to_string();
|
||||||
ret.content_types.insert(content_type);
|
ret.content_types.insert(content_type);
|
||||||
@ -591,13 +591,13 @@ impl DocumentsAggregator {
|
|||||||
|
|
||||||
self.updated |= other.updated;
|
self.updated |= other.updated;
|
||||||
// we can't create a union because there is no `into_union` method
|
// we can't create a union because there is no `into_union` method
|
||||||
for user_agent in other.user_agents.into_iter() {
|
for user_agent in other.user_agents {
|
||||||
self.user_agents.insert(user_agent);
|
self.user_agents.insert(user_agent);
|
||||||
}
|
}
|
||||||
for primary_key in other.primary_keys.into_iter() {
|
for primary_key in other.primary_keys {
|
||||||
self.primary_keys.insert(primary_key);
|
self.primary_keys.insert(primary_key);
|
||||||
}
|
}
|
||||||
for content_type in other.content_types.into_iter() {
|
for content_type in other.content_types {
|
||||||
self.content_types.insert(content_type);
|
self.content_types.insert(content_type);
|
||||||
}
|
}
|
||||||
self.index_creation |= other.index_creation;
|
self.index_creation |= other.index_creation;
|
||||||
|
@ -14,7 +14,6 @@ use serde_json::Value;
|
|||||||
use crate::analytics::{Analytics, SearchAggregator};
|
use crate::analytics::{Analytics, SearchAggregator};
|
||||||
use crate::extractors::authentication::{policies::*, GuardedData};
|
use crate::extractors::authentication::{policies::*, GuardedData};
|
||||||
use crate::extractors::sequential_extractor::SeqHandler;
|
use crate::extractors::sequential_extractor::SeqHandler;
|
||||||
use crate::routes::{fold_star_or, StarOr};
|
|
||||||
|
|
||||||
pub fn configure(cfg: &mut web::ServiceConfig) {
|
pub fn configure(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(
|
cfg.service(
|
||||||
@ -30,16 +29,16 @@ pub struct SearchQueryGet {
|
|||||||
q: Option<String>,
|
q: Option<String>,
|
||||||
offset: Option<usize>,
|
offset: Option<usize>,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
attributes_to_retrieve: Option<CS<StarOr<String>>>,
|
attributes_to_retrieve: Option<CS<String>>,
|
||||||
attributes_to_crop: Option<CS<StarOr<String>>>,
|
attributes_to_crop: Option<CS<String>>,
|
||||||
#[serde(default = "DEFAULT_CROP_LENGTH")]
|
#[serde(default = "DEFAULT_CROP_LENGTH")]
|
||||||
crop_length: usize,
|
crop_length: usize,
|
||||||
attributes_to_highlight: Option<CS<StarOr<String>>>,
|
attributes_to_highlight: Option<CS<String>>,
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
sort: Option<String>,
|
sort: Option<String>,
|
||||||
#[serde(default = "Default::default")]
|
#[serde(default = "Default::default")]
|
||||||
show_matches_position: bool,
|
show_matches_position: bool,
|
||||||
facets: Option<CS<StarOr<String>>>,
|
facets: Option<CS<String>>,
|
||||||
#[serde(default = "DEFAULT_HIGHLIGHT_PRE_TAG")]
|
#[serde(default = "DEFAULT_HIGHLIGHT_PRE_TAG")]
|
||||||
highlight_pre_tag: String,
|
highlight_pre_tag: String,
|
||||||
#[serde(default = "DEFAULT_HIGHLIGHT_POST_TAG")]
|
#[serde(default = "DEFAULT_HIGHLIGHT_POST_TAG")]
|
||||||
@ -62,14 +61,18 @@ impl From<SearchQueryGet> for SearchQuery {
|
|||||||
q: other.q,
|
q: other.q,
|
||||||
offset: other.offset,
|
offset: other.offset,
|
||||||
limit: other.limit.unwrap_or_else(DEFAULT_SEARCH_LIMIT),
|
limit: other.limit.unwrap_or_else(DEFAULT_SEARCH_LIMIT),
|
||||||
attributes_to_retrieve: other.attributes_to_retrieve.and_then(fold_star_or),
|
attributes_to_retrieve: other
|
||||||
attributes_to_crop: other.attributes_to_crop.and_then(fold_star_or),
|
.attributes_to_retrieve
|
||||||
|
.map(|o| o.into_iter().collect()),
|
||||||
|
attributes_to_crop: other.attributes_to_crop.map(|o| o.into_iter().collect()),
|
||||||
crop_length: other.crop_length,
|
crop_length: other.crop_length,
|
||||||
attributes_to_highlight: other.attributes_to_highlight.and_then(fold_star_or),
|
attributes_to_highlight: other
|
||||||
|
.attributes_to_highlight
|
||||||
|
.map(|o| o.into_iter().collect()),
|
||||||
filter,
|
filter,
|
||||||
sort: other.sort.map(|attr| fix_sort_query_parameters(&attr)),
|
sort: other.sort.map(|attr| fix_sort_query_parameters(&attr)),
|
||||||
show_matches_position: other.show_matches_position,
|
show_matches_position: other.show_matches_position,
|
||||||
facets: other.facets.and_then(fold_star_or),
|
facets: other.facets.map(|o| o.into_iter().collect()),
|
||||||
highlight_pre_tag: other.highlight_pre_tag,
|
highlight_pre_tag: other.highlight_pre_tag,
|
||||||
highlight_post_tag: other.highlight_post_tag,
|
highlight_post_tag: other.highlight_post_tag,
|
||||||
crop_marker: other.crop_marker,
|
crop_marker: other.crop_marker,
|
||||||
|
@ -318,7 +318,7 @@ make_setting_route!(
|
|||||||
"Pagination Updated".to_string(),
|
"Pagination Updated".to_string(),
|
||||||
json!({
|
json!({
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"limited_to": setting.as_ref().and_then(|s| s.limited_to.set()),
|
"max_total_hits": setting.as_ref().and_then(|s| s.max_total_hits.set()),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
Some(req),
|
Some(req),
|
||||||
@ -349,7 +349,9 @@ generate_configure!(
|
|||||||
stop_words,
|
stop_words,
|
||||||
synonyms,
|
synonyms,
|
||||||
ranking_rules,
|
ranking_rules,
|
||||||
typo_tolerance
|
typo_tolerance,
|
||||||
|
pagination,
|
||||||
|
faceting
|
||||||
);
|
);
|
||||||
|
|
||||||
pub async fn update_all(
|
pub async fn update_all(
|
||||||
@ -409,6 +411,18 @@ pub async fn update_all(
|
|||||||
.map(|s| s.two_typos.set()))
|
.map(|s| s.two_typos.set()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
},
|
},
|
||||||
|
"faceting": {
|
||||||
|
"max_values_per_facet": settings.faceting
|
||||||
|
.as_ref()
|
||||||
|
.set()
|
||||||
|
.and_then(|s| s.max_values_per_facet.as_ref().set()),
|
||||||
|
},
|
||||||
|
"pagination": {
|
||||||
|
"max_total_hits": settings.pagination
|
||||||
|
.as_ref()
|
||||||
|
.set()
|
||||||
|
.and_then(|s| s.max_total_hits.as_ref().set()),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
Some(&req),
|
Some(&req),
|
||||||
);
|
);
|
||||||
|
@ -25,7 +25,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
|
|||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
pub struct TaskFilterQuery {
|
pub struct TasksFilterQuery {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
type_: Option<CS<StarOr<TaskType>>>,
|
type_: Option<CS<StarOr<TaskType>>>,
|
||||||
status: Option<CS<StarOr<TaskStatus>>>,
|
status: Option<CS<StarOr<TaskStatus>>>,
|
||||||
@ -61,17 +61,11 @@ fn task_status_matches_events(status: &TaskStatus, events: &[TaskEvent]) -> bool
|
|||||||
|
|
||||||
async fn get_tasks(
|
async fn get_tasks(
|
||||||
meilisearch: GuardedData<ActionPolicy<{ actions::TASKS_GET }>, MeiliSearch>,
|
meilisearch: GuardedData<ActionPolicy<{ actions::TASKS_GET }>, MeiliSearch>,
|
||||||
params: web::Query<TaskFilterQuery>,
|
params: web::Query<TasksFilterQuery>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
analytics: web::Data<dyn Analytics>,
|
analytics: web::Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
analytics.publish(
|
let TasksFilterQuery {
|
||||||
"Tasks Seen".to_string(),
|
|
||||||
json!({ "per_task_uid": false }),
|
|
||||||
Some(&req),
|
|
||||||
);
|
|
||||||
|
|
||||||
let TaskFilterQuery {
|
|
||||||
type_,
|
type_,
|
||||||
status,
|
status,
|
||||||
index_uid,
|
index_uid,
|
||||||
@ -87,6 +81,16 @@ async fn get_tasks(
|
|||||||
let status: Option<Vec<_>> = status.and_then(fold_star_or);
|
let status: Option<Vec<_>> = status.and_then(fold_star_or);
|
||||||
let index_uid: Option<Vec<_>> = index_uid.and_then(fold_star_or);
|
let index_uid: Option<Vec<_>> = index_uid.and_then(fold_star_or);
|
||||||
|
|
||||||
|
analytics.publish(
|
||||||
|
"Tasks Seen".to_string(),
|
||||||
|
json!({
|
||||||
|
"filtered_by_index_uid": index_uid.as_ref().map_or(false, |v| !v.is_empty()),
|
||||||
|
"filtered_by_type": type_.as_ref().map_or(false, |v| !v.is_empty()),
|
||||||
|
"filtered_by_status": status.as_ref().map_or(false, |v| !v.is_empty()),
|
||||||
|
}),
|
||||||
|
Some(&req),
|
||||||
|
);
|
||||||
|
|
||||||
// Then we filter on potential indexes and make sure that the search filter
|
// Then we filter on potential indexes and make sure that the search filter
|
||||||
// restrictions are also applied.
|
// restrictions are also applied.
|
||||||
let indexes_filters = match index_uid {
|
let indexes_filters = match index_uid {
|
||||||
|
@ -42,6 +42,7 @@ async fn add_valid_api_key() {
|
|||||||
"name": "indexing-key",
|
"name": "indexing-key",
|
||||||
"description": "Indexing API key",
|
"description": "Indexing API key",
|
||||||
"uid": "4bc0887a-0e41-4f3b-935d-0c451dcee9c8",
|
"uid": "4bc0887a-0e41-4f3b-935d-0c451dcee9c8",
|
||||||
|
"key": "d9e776b8412f1db6974c9a5556b961c3559440b6588216f4ea5d9ed49f7c8f3c",
|
||||||
"indexes": ["products"],
|
"indexes": ["products"],
|
||||||
"actions": [
|
"actions": [
|
||||||
"search",
|
"search",
|
||||||
|
@ -222,7 +222,7 @@ impl Index<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn search_get(&self, query: Value) -> (Value, StatusCode) {
|
pub async fn search_get(&self, query: Value) -> (Value, StatusCode) {
|
||||||
let params = serde_url_params::to_string(&query).unwrap();
|
let params = yaup::to_string(&query).unwrap();
|
||||||
let url = format!("/indexes/{}/search?{}", encode(self.uid.as_ref()), params);
|
let url = format!("/indexes/{}/search?{}", encode(self.uid.as_ref()), params);
|
||||||
self.service.get(url).await
|
self.service.get(url).await
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ async fn import_dump_v2_movie_raw() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({"displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({"displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -125,7 +125,7 @@ async fn import_dump_v2_movie_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -189,7 +189,7 @@ async fn import_dump_v2_rubygems_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({"displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 }})
|
json!({"displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 }})
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -253,7 +253,7 @@ async fn import_dump_v3_movie_raw() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({"displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({"displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -317,7 +317,7 @@ async fn import_dump_v3_movie_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -381,7 +381,7 @@ async fn import_dump_v3_rubygems_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({"displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({"displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -445,7 +445,7 @@ async fn import_dump_v4_movie_raw() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({ "displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({ "displayedAttributes": ["*"], "searchableAttributes": ["*"], "filterableAttributes": [], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -509,7 +509,7 @@ async fn import_dump_v4_movie_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({ "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": [], "rankingRules": ["words", "typo", "proximity", "attribute", "exactness"], "stopWords": ["of", "the"], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 }, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
@ -573,7 +573,7 @@ async fn import_dump_v4_rubygems_with_settings() {
|
|||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings,
|
settings,
|
||||||
json!({ "displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "limitedTo": 1000 } })
|
json!({ "displayedAttributes": ["name", "summary", "description", "version", "total_downloads"], "searchableAttributes": ["name", "summary"], "filterableAttributes": ["version"], "sortableAttributes": [], "rankingRules": ["typo", "words", "fame:desc", "proximity", "attribute", "exactness", "total_downloads:desc"], "stopWords": [], "synonyms": {}, "distinctAttribute": null, "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 5, "twoTypos": 9}, "disableOnWords": [], "disableOnAttributes": [] }, "faceting": { "maxValuesPerFacet": 100 }, "pagination": { "maxTotalHits": 1000 } })
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tasks, code) = index.list_tasks().await;
|
let (tasks, code) = index.list_tasks().await;
|
||||||
|
@ -45,26 +45,18 @@ async fn search_invalid_highlight_and_crop_tags() {
|
|||||||
|
|
||||||
for field in fields {
|
for field in fields {
|
||||||
// object
|
// object
|
||||||
index
|
let (response, code) = index
|
||||||
.search(
|
.search_post(json!({field.to_string(): {"marker": "<crop>"}}))
|
||||||
json!({field.to_string(): {"marker": "<crop>"}}),
|
|
||||||
|response, code| {
|
|
||||||
assert_eq!(code, 400, "field {} passing object: {}", &field, response);
|
|
||||||
assert_eq!(response["code"], "bad_request");
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
|
assert_eq!(code, 400, "field {} passing object: {}", &field, response);
|
||||||
|
assert_eq!(response["code"], "bad_request");
|
||||||
|
|
||||||
// array
|
// array
|
||||||
index
|
let (response, code) = index
|
||||||
.search(
|
.search_post(json!({field.to_string(): ["marker", "<crop>"]}))
|
||||||
json!({field.to_string(): ["marker", "<crop>"]}),
|
|
||||||
|response, code| {
|
|
||||||
assert_eq!(code, 400, "field {} passing array: {}", &field, response);
|
|
||||||
assert_eq!(response["code"], "bad_request");
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
.await;
|
||||||
|
assert_eq!(code, 400, "field {} passing array: {}", &field, response);
|
||||||
|
assert_eq!(response["code"], "bad_request");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +107,7 @@ async fn filter_invalid_syntax_array() {
|
|||||||
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
||||||
});
|
});
|
||||||
index
|
index
|
||||||
.search(json!({"filter": [["title & Glass"]]}), |response, code| {
|
.search(json!({"filter": ["title & Glass"]}), |response, code| {
|
||||||
assert_eq!(response, expected_response);
|
assert_eq!(response, expected_response);
|
||||||
assert_eq!(code, 400);
|
assert_eq!(code, 400);
|
||||||
})
|
})
|
||||||
@ -172,7 +164,7 @@ async fn filter_invalid_attribute_array() {
|
|||||||
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
||||||
});
|
});
|
||||||
index
|
index
|
||||||
.search(json!({"filter": [["many = Glass"]]}), |response, code| {
|
.search(json!({"filter": ["many = Glass"]}), |response, code| {
|
||||||
assert_eq!(response, expected_response);
|
assert_eq!(response, expected_response);
|
||||||
assert_eq!(code, 400);
|
assert_eq!(code, 400);
|
||||||
})
|
})
|
||||||
@ -226,7 +218,7 @@ async fn filter_reserved_geo_attribute_array() {
|
|||||||
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
||||||
});
|
});
|
||||||
index
|
index
|
||||||
.search(json!({"filter": [["_geo = Glass"]]}), |response, code| {
|
.search(json!({"filter": ["_geo = Glass"]}), |response, code| {
|
||||||
assert_eq!(response, expected_response);
|
assert_eq!(response, expected_response);
|
||||||
assert_eq!(code, 400);
|
assert_eq!(code, 400);
|
||||||
})
|
})
|
||||||
@ -281,7 +273,7 @@ async fn filter_reserved_attribute_array() {
|
|||||||
});
|
});
|
||||||
index
|
index
|
||||||
.search(
|
.search(
|
||||||
json!({"filter": [["_geoDistance = Glass"]]}),
|
json!({"filter": ["_geoDistance = Glass"]}),
|
||||||
|response, code| {
|
|response, code| {
|
||||||
assert_eq!(response, expected_response);
|
assert_eq!(response, expected_response);
|
||||||
assert_eq!(code, 400);
|
assert_eq!(code, 400);
|
||||||
|
@ -15,85 +15,100 @@ async fn formatted_contain_wildcard() {
|
|||||||
index.add_documents(documents, None).await;
|
index.add_documents(documents, None).await;
|
||||||
index.wait_task(1).await;
|
index.wait_task(1).await;
|
||||||
|
|
||||||
let (response, code) = index
|
index.search(json!({ "q": "pesti", "attributesToRetrieve": ["father", "mother"], "attributesToHighlight": ["father", "mother", "*"], "attributesToCrop": ["doggos"], "showMatchesPosition": true }),
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": ["father", "mother"], "attributesToHighlight": ["father", "mother", "*"], "attributesToCrop": ["doggos"], "showMatchesPosition": true }))
|
|response, code|
|
||||||
.await;
|
{
|
||||||
assert_eq!(code, 200, "{}", response);
|
assert_eq!(code, 200, "{}", response);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response["hits"][0],
|
response["hits"][0],
|
||||||
json!({
|
json!({
|
||||||
"_formatted": {
|
"_formatted": {
|
||||||
"id": "852",
|
"id": "852",
|
||||||
"cattos": "<em>pesti</em>",
|
"cattos": "<em>pesti</em>",
|
||||||
|
},
|
||||||
|
"_matchesPosition": {"cattos": [{"start": 0, "length": 5}]},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "q": "pesti", "attributesToRetrieve": ["*"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"cattos": "pesti",
|
||||||
|
})
|
||||||
|
);
|
||||||
},
|
},
|
||||||
"_matchesPosition": {"cattos": [{"start": 0, "length": 5}]},
|
)
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": ["*"] }))
|
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"cattos": "pesti",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(
|
.search(
|
||||||
json!({ "q": "pesti", "attributesToRetrieve": ["*"], "attributesToHighlight": ["id"], "showMatchesPosition": true }),
|
json!({ "q": "pesti", "attributesToRetrieve": ["*"], "attributesToHighlight": ["id"], "showMatchesPosition": true }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"cattos": "pesti",
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
"cattos": "pesti",
|
||||||
|
},
|
||||||
|
"_matchesPosition": {"cattos": [{"start": 0, "length": 5}]},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"cattos": "pesti",
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
"cattos": "pesti",
|
|
||||||
},
|
|
||||||
"_matchesPosition": {"cattos": [{"start": 0, "length": 5}]},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(
|
.search(
|
||||||
json!({ "q": "pesti", "attributesToRetrieve": ["*"], "attributesToCrop": ["*"] }),
|
json!({ "q": "pesti", "attributesToRetrieve": ["*"], "attributesToCrop": ["*"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"cattos": "pesti",
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
"cattos": "pesti",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"cattos": "pesti",
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
"cattos": "pesti",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "q": "pesti", "attributesToCrop": ["*"] }))
|
.search(
|
||||||
|
json!({ "q": "pesti", "attributesToCrop": ["*"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"cattos": "pesti",
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
"cattos": "pesti",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"cattos": "pesti",
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
"cattos": "pesti",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@ -105,108 +120,122 @@ async fn format_nested() {
|
|||||||
index.add_documents(documents, None).await;
|
index.add_documents(documents, None).await;
|
||||||
index.wait_task(0).await;
|
index.wait_task(0).await;
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": ["doggos"] }))
|
.search(
|
||||||
.await;
|
json!({ "q": "pesti", "attributesToRetrieve": ["doggos"] }),
|
||||||
assert_eq!(code, 200, "{}", response);
|
|response, code| {
|
||||||
assert_eq!(
|
assert_eq!(code, 200, "{}", response);
|
||||||
response["hits"][0],
|
assert_eq!(
|
||||||
json!({
|
response["hits"][0],
|
||||||
"doggos": [
|
json!({
|
||||||
{
|
"doggos": [
|
||||||
"name": "bobby",
|
{
|
||||||
"age": 2,
|
"name": "bobby",
|
||||||
},
|
"age": 2,
|
||||||
{
|
},
|
||||||
"name": "buddy",
|
{
|
||||||
"age": 4,
|
"name": "buddy",
|
||||||
},
|
"age": 4,
|
||||||
],
|
},
|
||||||
})
|
],
|
||||||
);
|
})
|
||||||
|
);
|
||||||
let (response, code) = index
|
},
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": ["doggos.name"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"doggos": [
|
|
||||||
{
|
|
||||||
"name": "bobby",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "buddy",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(
|
|
||||||
json!({ "q": "bobby", "attributesToRetrieve": ["doggos.name"], "showMatchesPosition": true }),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"doggos": [
|
|
||||||
{
|
|
||||||
"name": "bobby",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "buddy",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"_matchesPosition": {"doggos.name": [{"start": 0, "length": 5}]},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToHighlight": ["doggos.name"] }))
|
.search(
|
||||||
.await;
|
json!({ "q": "pesti", "attributesToRetrieve": ["doggos.name"] }),
|
||||||
assert_eq!(code, 200, "{}", response);
|
|response, code| {
|
||||||
assert_eq!(
|
assert_eq!(code, 200, "{}", response);
|
||||||
response["hits"][0],
|
assert_eq!(
|
||||||
json!({
|
response["hits"][0],
|
||||||
"_formatted": {
|
json!({
|
||||||
"doggos": [
|
"doggos": [
|
||||||
{
|
{
|
||||||
"name": "bobby",
|
"name": "bobby",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "buddy",
|
"name": "buddy",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToCrop": ["doggos.name"] }))
|
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"_formatted": {
|
|
||||||
"doggos": [
|
|
||||||
{
|
|
||||||
"name": "bobby",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "buddy",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": ["doggos.name"], "attributesToHighlight": ["doggos.age"] }))
|
.search(
|
||||||
|
json!({ "q": "bobby", "attributesToRetrieve": ["doggos.name"], "showMatchesPosition": true }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"doggos": [
|
||||||
|
{
|
||||||
|
"name": "bobby",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buddy",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"_matchesPosition": {"doggos.name": [{"start": 0, "length": 5}]},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToHighlight": ["doggos.name"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"_formatted": {
|
||||||
|
"doggos": [
|
||||||
|
{
|
||||||
|
"name": "bobby",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buddy",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToCrop": ["doggos.name"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"_formatted": {
|
||||||
|
"doggos": [
|
||||||
|
{
|
||||||
|
"name": "bobby",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buddy",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(json!({ "q": "pesti", "attributesToRetrieve": ["doggos.name"], "attributesToHighlight": ["doggos.age"] }),
|
||||||
|
|response, code| {
|
||||||
assert_eq!(code, 200, "{}", response);
|
assert_eq!(code, 200, "{}", response);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response["hits"][0],
|
response["hits"][0],
|
||||||
@ -233,11 +262,13 @@ async fn format_nested() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
})
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToHighlight": ["doggos.age"], "attributesToCrop": ["doggos.name"] }))
|
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
|
index
|
||||||
|
.search(json!({ "q": "pesti", "attributesToRetrieve": [], "attributesToHighlight": ["doggos.age"], "attributesToCrop": ["doggos.name"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response["hits"][0],
|
response["hits"][0],
|
||||||
json!({
|
json!({
|
||||||
@ -255,6 +286,9 @@ async fn format_nested() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@ -271,9 +305,9 @@ async fn displayedattr_2_smol() {
|
|||||||
index.add_documents(documents, None).await;
|
index.add_documents(documents, None).await;
|
||||||
index.wait_task(1).await;
|
index.wait_task(1).await;
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "attributesToRetrieve": ["father", "id"], "attributesToHighlight": ["mother"], "attributesToCrop": ["cattos"] }))
|
.search(json!({ "attributesToRetrieve": ["father", "id"], "attributesToHighlight": ["mother"], "attributesToCrop": ["cattos"] }),
|
||||||
.await;
|
|response, code| {
|
||||||
assert_eq!(code, 200, "{}", response);
|
assert_eq!(code, 200, "{}", response);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response["hits"][0],
|
response["hits"][0],
|
||||||
@ -281,119 +315,157 @@ async fn displayedattr_2_smol() {
|
|||||||
"id": 852,
|
"id": 852,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToRetrieve": ["id"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
})
|
})
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToHighlight": ["id"] }))
|
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "attributesToCrop": ["id"] }))
|
.search(
|
||||||
.await;
|
json!({ "attributesToRetrieve": ["id"] }),
|
||||||
assert_eq!(code, 200, "{}", response);
|
|response, code| {
|
||||||
assert_eq!(
|
assert_eq!(code, 200, "{}", response);
|
||||||
response["hits"][0],
|
assert_eq!(
|
||||||
json!({
|
response["hits"][0],
|
||||||
"id": 852,
|
json!({
|
||||||
"_formatted": {
|
"id": 852,
|
||||||
"id": "852",
|
})
|
||||||
}
|
);
|
||||||
})
|
},
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToHighlight": ["id"], "attributesToCrop": ["id"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToHighlight": ["cattos"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToCrop": ["cattos"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"id": 852,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToRetrieve": ["cattos"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(response["hits"][0], json!({}));
|
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(
|
|
||||||
json!({ "attributesToRetrieve": ["cattos"], "attributesToHighlight": ["cattos"], "attributesToCrop": ["cattos"] }),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToHighlight": ["id"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(json!({ "attributesToCrop": ["id"] }), |response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToHighlight": ["id"], "attributesToCrop": ["id"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToHighlight": ["cattos"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToCrop": ["cattos"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"id": 852,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToRetrieve": ["cattos"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(response["hits"][0], json!({}));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToRetrieve": ["cattos"], "attributesToHighlight": ["cattos"], "attributesToCrop": ["cattos"] }),
|
||||||
|
|response, code| {
|
||||||
assert_eq!(code, 200, "{}", response);
|
assert_eq!(code, 200, "{}", response);
|
||||||
assert_eq!(response["hits"][0], json!({}));
|
assert_eq!(response["hits"][0], json!({}));
|
||||||
|
|
||||||
let (response, code) = index
|
|
||||||
.search_post(json!({ "attributesToRetrieve": ["cattos"], "attributesToHighlight": ["id"] }))
|
|
||||||
.await;
|
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
);
|
.await;
|
||||||
|
|
||||||
let (response, code) = index
|
index
|
||||||
.search_post(json!({ "attributesToRetrieve": ["cattos"], "attributesToCrop": ["id"] }))
|
.search(
|
||||||
|
json!({ "attributesToRetrieve": ["cattos"], "attributesToHighlight": ["id"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
index
|
||||||
|
.search(
|
||||||
|
json!({ "attributesToRetrieve": ["cattos"], "attributesToCrop": ["id"] }),
|
||||||
|
|response, code| {
|
||||||
|
assert_eq!(code, 200, "{}", response);
|
||||||
|
assert_eq!(
|
||||||
|
response["hits"][0],
|
||||||
|
json!({
|
||||||
|
"_formatted": {
|
||||||
|
"id": "852",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(code, 200, "{}", response);
|
|
||||||
assert_eq!(
|
|
||||||
response["hits"][0],
|
|
||||||
json!({
|
|
||||||
"_formatted": {
|
|
||||||
"id": "852",
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -567,7 +567,7 @@ async fn placeholder_search_is_hard_limited() {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
index
|
index
|
||||||
.update_settings(json!({ "pagination": { "limitedTo": 10_000 } }))
|
.update_settings(json!({ "pagination": { "maxTotalHits": 10_000 } }))
|
||||||
.await;
|
.await;
|
||||||
index.wait_task(1).await;
|
index.wait_task(1).await;
|
||||||
|
|
||||||
@ -636,7 +636,7 @@ async fn search_is_hard_limited() {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
index
|
index
|
||||||
.update_settings(json!({ "pagination": { "limitedTo": 10_000 } }))
|
.update_settings(json!({ "pagination": { "maxTotalHits": 10_000 } }))
|
||||||
.await;
|
.await;
|
||||||
index.wait_task(1).await;
|
index.wait_task(1).await;
|
||||||
|
|
||||||
|
@ -27,7 +27,13 @@ static DEFAULT_SETTINGS_VALUES: Lazy<HashMap<&'static str, Value>> = Lazy::new(|
|
|||||||
map.insert(
|
map.insert(
|
||||||
"faceting",
|
"faceting",
|
||||||
json!({
|
json!({
|
||||||
"maxValuesByFacet": json!(100),
|
"maxValuesPerFacet": json!(100),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
map.insert(
|
||||||
|
"pagination",
|
||||||
|
json!({
|
||||||
|
"maxTotalHits": json!(1000),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
map
|
map
|
||||||
@ -76,7 +82,7 @@ async fn get_settings() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
settings["pagination"],
|
settings["pagination"],
|
||||||
json!({
|
json!({
|
||||||
"limitedTo": 1000,
|
"maxTotalHits": 1000,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -206,7 +212,7 @@ async fn error_update_setting_unexisting_index_invalid_uid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! test_setting_routes {
|
macro_rules! test_setting_routes {
|
||||||
($($setting:ident), *) => {
|
($($setting:ident $write_method:ident), *) => {
|
||||||
$(
|
$(
|
||||||
mod $setting {
|
mod $setting {
|
||||||
use crate::common::Server;
|
use crate::common::Server;
|
||||||
@ -232,7 +238,7 @@ macro_rules! test_setting_routes {
|
|||||||
.chars()
|
.chars()
|
||||||
.map(|c| if c == '_' { '-' } else { c })
|
.map(|c| if c == '_' { '-' } else { c })
|
||||||
.collect::<String>());
|
.collect::<String>());
|
||||||
let (response, code) = server.service.put(url, serde_json::Value::Null).await;
|
let (response, code) = server.service.$write_method(url, serde_json::Value::Null).await;
|
||||||
assert_eq!(code, 202, "{}", response);
|
assert_eq!(code, 202, "{}", response);
|
||||||
server.index("").wait_task(0).await;
|
server.index("").wait_task(0).await;
|
||||||
let (response, code) = server.index("test").get().await;
|
let (response, code) = server.index("test").get().await;
|
||||||
@ -276,13 +282,15 @@ macro_rules! test_setting_routes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_setting_routes!(
|
test_setting_routes!(
|
||||||
filterable_attributes,
|
filterable_attributes put,
|
||||||
displayed_attributes,
|
displayed_attributes put,
|
||||||
searchable_attributes,
|
searchable_attributes put,
|
||||||
distinct_attribute,
|
distinct_attribute put,
|
||||||
stop_words,
|
stop_words put,
|
||||||
ranking_rules,
|
ranking_rules put,
|
||||||
synonyms
|
synonyms put,
|
||||||
|
pagination patch,
|
||||||
|
faceting patch
|
||||||
);
|
);
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
@ -3,8 +3,6 @@ name = "meilisearch-lib"
|
|||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "4.0.1", default-features = false }
|
actix-web = { version = "4.0.1", default-features = false }
|
||||||
anyhow = { version = "1.0.56", features = ["backtrace"] }
|
anyhow = { version = "1.0.56", features = ["backtrace"] }
|
||||||
@ -30,7 +28,7 @@ lazy_static = "1.4.0"
|
|||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
meilisearch-auth = { path = "../meilisearch-auth" }
|
meilisearch-auth = { path = "../meilisearch-auth" }
|
||||||
meilisearch-types = { path = "../meilisearch-types" }
|
meilisearch-types = { path = "../meilisearch-types" }
|
||||||
milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.29.3" }
|
milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.31.1" }
|
||||||
mime = "0.3.16"
|
mime = "0.3.16"
|
||||||
num_cpus = "1.13.1"
|
num_cpus = "1.13.1"
|
||||||
obkv = "0.2.0"
|
obkv = "0.2.0"
|
||||||
@ -53,7 +51,7 @@ tempfile = "3.3.0"
|
|||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
|
||||||
tokio = { version = "1.17.0", features = ["full"] }
|
tokio = { version = "1.17.0", features = ["full"] }
|
||||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
uuid = { version = "1.1.2", features = ["serde", "v4"] }
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.3.2"
|
||||||
whoami = { version = "1.2.1", optional = true }
|
whoami = { version = "1.2.1", optional = true }
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ const DATA_FILE_NAME: &str = "documents.jsonl";
|
|||||||
impl Index {
|
impl Index {
|
||||||
pub fn dump(&self, path: impl AsRef<Path>) -> Result<()> {
|
pub fn dump(&self, path: impl AsRef<Path>) -> Result<()> {
|
||||||
// acquire write txn make sure any ongoing write is finished before we start.
|
// acquire write txn make sure any ongoing write is finished before we start.
|
||||||
let txn = self.env.write_txn()?;
|
let txn = self.write_txn()?;
|
||||||
let path = path.as_ref().join(format!("indexes/{}", self.uuid));
|
let path = path.as_ref().join(format!("indexes/{}", self.uuid));
|
||||||
|
|
||||||
create_dir_all(&path)?;
|
create_dir_all(&path)?;
|
||||||
|
@ -4,9 +4,10 @@ use std::marker::PhantomData;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use fst::IntoStreamer;
|
use fst::IntoStreamer;
|
||||||
use milli::heed::{EnvOpenOptions, RoTxn};
|
use milli::heed::{CompactionOption, EnvOpenOptions, RoTxn};
|
||||||
use milli::update::{IndexerConfig, Setting};
|
use milli::update::{IndexerConfig, Setting};
|
||||||
use milli::{obkv_to_json, FieldDistribution, DEFAULT_VALUES_PER_FACET};
|
use milli::{obkv_to_json, FieldDistribution, DEFAULT_VALUES_PER_FACET};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -14,8 +15,7 @@ use serde_json::{Map, Value};
|
|||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::index::search::DEFAULT_PAGINATION_LIMITED_TO;
|
use crate::index::search::DEFAULT_PAGINATION_MAX_TOTAL_HITS;
|
||||||
use crate::EnvSizer;
|
|
||||||
|
|
||||||
use super::error::IndexError;
|
use super::error::IndexError;
|
||||||
use super::error::Result;
|
use super::error::Result;
|
||||||
@ -202,9 +202,9 @@ impl Index {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let pagination = PaginationSettings {
|
let pagination = PaginationSettings {
|
||||||
limited_to: Setting::Set(
|
max_total_hits: Setting::Set(
|
||||||
self.pagination_limited_to(txn)?
|
self.pagination_max_total_hits(txn)?
|
||||||
.unwrap_or(DEFAULT_PAGINATION_LIMITED_TO),
|
.unwrap_or(DEFAULT_PAGINATION_MAX_TOTAL_HITS),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ impl Index {
|
|||||||
let fields_ids_map = self.fields_ids_map(&txn)?;
|
let fields_ids_map = self.fields_ids_map(&txn)?;
|
||||||
let all_fields: Vec<_> = fields_ids_map.iter().map(|(id, _)| id).collect();
|
let all_fields: Vec<_> = fields_ids_map.iter().map(|(id, _)| id).collect();
|
||||||
|
|
||||||
let iter = self.documents.range(&txn, &(..))?.skip(offset).take(limit);
|
let iter = self.all_documents(&txn)?.skip(offset).take(limit);
|
||||||
|
|
||||||
let mut documents = Vec::new();
|
let mut documents = Vec::new();
|
||||||
|
|
||||||
@ -302,7 +302,12 @@ impl Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> u64 {
|
pub fn size(&self) -> u64 {
|
||||||
self.env.size()
|
WalkDir::new(self.inner.path())
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| entry.ok())
|
||||||
|
.filter_map(|entry| entry.metadata().ok())
|
||||||
|
.filter(|metadata| metadata.is_file())
|
||||||
|
.fold(0, |acc, m| acc + m.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshot(&self, path: impl AsRef<Path>) -> Result<()> {
|
pub fn snapshot(&self, path: impl AsRef<Path>) -> Result<()> {
|
||||||
@ -310,9 +315,7 @@ impl Index {
|
|||||||
create_dir_all(&dst)?;
|
create_dir_all(&dst)?;
|
||||||
dst.push("data.mdb");
|
dst.push("data.mdb");
|
||||||
let _txn = self.write_txn()?;
|
let _txn = self.write_txn()?;
|
||||||
self.inner
|
self.inner.copy_to_path(dst, CompactionOption::Enabled)?;
|
||||||
.env
|
|
||||||
.copy_to_path(dst, milli::heed::CompactionOption::Enabled)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub const DEFAULT_HIGHLIGHT_POST_TAG: fn() -> String = || "</em>".to_string();
|
|||||||
|
|
||||||
/// The maximimum number of results that the engine
|
/// The maximimum number of results that the engine
|
||||||
/// will be able to return in one search call.
|
/// will be able to return in one search call.
|
||||||
pub const DEFAULT_PAGINATION_LIMITED_TO: usize = 1000;
|
pub const DEFAULT_PAGINATION_MAX_TOTAL_HITS: usize = 1000;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Deserialize, Debug, Clone, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
@ -91,14 +91,14 @@ impl Index {
|
|||||||
search.query(query);
|
search.query(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pagination_limited_to = self
|
let max_total_hits = self
|
||||||
.pagination_limited_to(&rtxn)?
|
.pagination_max_total_hits(&rtxn)?
|
||||||
.unwrap_or(DEFAULT_PAGINATION_LIMITED_TO);
|
.unwrap_or(DEFAULT_PAGINATION_MAX_TOTAL_HITS);
|
||||||
|
|
||||||
// Make sure that a user can't get more documents than the hard limit,
|
// Make sure that a user can't get more documents than the hard limit,
|
||||||
// we align that on the offset too.
|
// we align that on the offset too.
|
||||||
let offset = min(query.offset.unwrap_or(0), pagination_limited_to);
|
let offset = min(query.offset.unwrap_or(0), max_total_hits);
|
||||||
let limit = min(query.limit, pagination_limited_to.saturating_sub(offset));
|
let limit = min(query.limit, max_total_hits.saturating_sub(offset));
|
||||||
|
|
||||||
search.offset(offset);
|
search.offset(offset);
|
||||||
search.limit(limit);
|
search.limit(limit);
|
||||||
|
@ -86,7 +86,7 @@ pub struct FacetingSettings {
|
|||||||
pub struct PaginationSettings {
|
pub struct PaginationSettings {
|
||||||
#[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))]
|
#[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))]
|
||||||
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
|
#[serde(default, skip_serializing_if = "Setting::is_not_set")]
|
||||||
pub limited_to: Setting<usize>,
|
pub max_total_hits: Setting<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds all the settings for an index. `T` can either be `Checked` if they represents settings
|
/// Holds all the settings for an index. `T` can either be `Checked` if they represents settings
|
||||||
@ -474,12 +474,12 @@ pub fn apply_settings_to_builder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match settings.pagination {
|
match settings.pagination {
|
||||||
Setting::Set(ref value) => match value.limited_to {
|
Setting::Set(ref value) => match value.max_total_hits {
|
||||||
Setting::Set(val) => builder.set_pagination_limited_to(val),
|
Setting::Set(val) => builder.set_pagination_max_total_hits(val),
|
||||||
Setting::Reset => builder.reset_pagination_limited_to(),
|
Setting::Reset => builder.reset_pagination_max_total_hits(),
|
||||||
Setting::NotSet => (),
|
Setting::NotSet => (),
|
||||||
},
|
},
|
||||||
Setting::Reset => builder.reset_pagination_limited_to(),
|
Setting::Reset => builder.reset_pagination_max_total_hits(),
|
||||||
Setting::NotSet => (),
|
Setting::NotSet => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use std::fs::{create_dir_all, File};
|
|||||||
use std::io::{BufRead, BufReader, Write};
|
use std::io::{BufRead, BufReader, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use milli::heed::types::{SerdeBincode, Str};
|
use milli::heed::types::{SerdeBincode, Str};
|
||||||
use milli::heed::{CompactionOption, Database, Env};
|
use milli::heed::{CompactionOption, Database, Env};
|
||||||
@ -11,7 +12,6 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use super::error::{IndexResolverError, Result};
|
use super::error::{IndexResolverError, Result};
|
||||||
use crate::tasks::task::TaskId;
|
use crate::tasks::task::TaskId;
|
||||||
use crate::EnvSizer;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct DumpEntry {
|
pub struct DumpEntry {
|
||||||
@ -131,7 +131,12 @@ impl HeedMetaStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_size(&self) -> Result<u64> {
|
fn get_size(&self) -> Result<u64> {
|
||||||
Ok(self.env.size())
|
Ok(WalkDir::new(self.env.path())
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| entry.ok())
|
||||||
|
.filter_map(|entry| entry.metadata().ok())
|
||||||
|
.filter(|metadata| metadata.is_file())
|
||||||
|
.fold(0, |acc, m| acc + m.len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump(&self, path: PathBuf) -> Result<()> {
|
pub fn dump(&self, path: PathBuf) -> Result<()> {
|
||||||
|
@ -20,23 +20,6 @@ pub use milli::heed;
|
|||||||
mod compression;
|
mod compression;
|
||||||
pub mod document_formats;
|
pub mod document_formats;
|
||||||
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
pub trait EnvSizer {
|
|
||||||
fn size(&self) -> u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EnvSizer for milli::heed::Env {
|
|
||||||
fn size(&self) -> u64 {
|
|
||||||
WalkDir::new(self.path())
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|entry| entry.ok())
|
|
||||||
.filter_map(|entry| entry.metadata().ok())
|
|
||||||
.filter(|metadata| metadata.is_file())
|
|
||||||
.fold(0, |acc, m| acc + m.len())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a db is empty. It does not provide any information on the
|
/// Check if a db is empty. It does not provide any information on the
|
||||||
/// validity of the data in it.
|
/// validity of the data in it.
|
||||||
/// We consider a database as non empty when it's a non empty directory.
|
/// We consider a database as non empty when it's a non empty directory.
|
||||||
|
@ -7,6 +7,7 @@ use anyhow::bail;
|
|||||||
use fs_extra::dir::{self, CopyOptions};
|
use fs_extra::dir::{self, CopyOptions};
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use meilisearch_auth::open_auth_store_env;
|
use meilisearch_auth::open_auth_store_env;
|
||||||
|
use milli::heed::CompactionOption;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
@ -181,9 +182,7 @@ impl SnapshotJob {
|
|||||||
let mut options = milli::heed::EnvOpenOptions::new();
|
let mut options = milli::heed::EnvOpenOptions::new();
|
||||||
options.map_size(self.index_size);
|
options.map_size(self.index_size);
|
||||||
let index = milli::Index::new(options, entry.path())?;
|
let index = milli::Index::new(options, entry.path())?;
|
||||||
index
|
index.copy_to_path(dst, CompactionOption::Enabled)?;
|
||||||
.env
|
|
||||||
.copy_to_path(dst, milli::heed::CompactionOption::Enabled)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "permissive-json-pointer"
|
name = "permissive-json-pointer"
|
||||||
version = "0.2.0"
|
version = "0.28.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A permissive json pointer"
|
description = "A permissive json pointer"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
Loading…
Reference in New Issue
Block a user