Preparing your documents
In this guide, you will learn about Meilisearch’s approach to date and time values, how to prepare your dataset for indexing, and how to chronologically sort and filter search results.
Preparing your documents
To filter and sort search results chronologically, your documents must have at least one field containing a UNIX timestamp. You may also use a string with a date in a format that can be sorted lexicographically, such as “2025-01-13”.
As an example, consider a database of video games. In this dataset, the release year is formatted as a timestamp:
[
{
"id": 0,
"title": "Return of the Obra Dinn",
"genre": "adventure",
"release_timestamp": 1538949600
},
{
"id": 1,
"title": "The Excavation of Hob's Barrow",
"genre": "adventure",
"release_timestamp": 1664316000
},
{
"id": 2,
"title": "Bayonetta 2",
"genre": "action",
"release_timestamp": 1411164000
}
]
Once all documents in your dataset have a date field, index your data as usual. The example below adds a videogame dataset to a games index:
cURL
JS
Python
PHP
Java
Ruby
Go
C#
Rust
Swift
Dart
curl \
-X POST 'MEILISEARCH_URL/indexes/games/documents' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data-binary @games.json
const games = require('./games.json')
client.index('games').addDocuments(games).then((res) => console.log(res))
import json
json_file = open('./games.json', encoding='utf-8')
games = json.load(json_file)
client.index('games').add_documents(games)
$gamesJson = file_get_contents('games.json');
$games = json_decode($gamesJson);
$client->index('games')->addDocuments($games);
import com.meilisearch.sdk;
import org.json.JSONArray;
import java.nio.file.Files;
import java.nio.file.Path;
Path fileName = Path.of("games.json");
String gamesJson = Files.readString(fileName);
Index index = client.index("games");
index.addDocuments(gamesJson);
require 'json'
games = JSON.parse(File.read('games.json'))
client.index('games').add_documents(games)
jsonFile, _ := os.Open("games.json")
defer jsonFile.Close()
byteValue, _ := io.ReadAll(jsonFile)
var games []map[string]interface{}
json.Unmarshal(byteValue, &games)
client.Index("games").AddDocuments(games, nil)
string jsonString = await File.ReadAllTextAsync("games.json");
var games = JsonSerializer.Deserialize<IEnumerable<Movie>>(jsonString, options);
var index = client.Index("games");
await index.AddDocumentsAsync<Movie>(games);
let mut file = File::open("games.json")
.unwrap();
let mut content = String::new();
file
.read_to_string(&mut content)
.unwrap();
let docs: Vec<Game> = serde_json::from_str(&content)
.unwrap();
client
.index("games")
.add_documents(&docs, None)
.await
.unwrap();
let path = Bundle.main.url(forResource: "games", withExtension: "json")!
let documents: Data = try Data(contentsOf: path)
client.index("games").addDocuments(documents: documents) { (result) in
switch result {
case .success(let task):
print(task)
case .failure(let error):
print(error)
}
}
//import 'dart:io';
//import 'dart:convert';
final json = await File('games.json').readAsString();
await client.index('games').addDocumentsJson(json);
Filtering by date
To filter search results based on their timestamp, add your document’s timestamp field to the list of filterableAttributes:
cURL
JS
Python
PHP
Java
Ruby
Go
C#
Rust
Swift
Dart
curl \
-X PUT 'MEILISEARCH_URL/indexes/games/settings/filterable-attributes' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data-binary '[
"release_timestamp"
]'
client.index('games').updateFilterableAttributes(['release_timestamp'])
client.index('games').update_filterable_attributes(['release_timestamp'])
$client->index('games')->updateFilterableAttributes(['release_timestamp']);
client.index("movies").updateFilterableAttributesSettings(
new String[] { "release_timestamp" });
client.index('games').update_filterable_attributes(['release_timestamp'])
filterableAttributes := []interface{}{"release_timestamp"}
client.Index("games").UpdateFilterableAttributes(&filterableAttributes)
await client.Index("games").UpdateFilterableAttributesAsync(new string[] { "release_timestamp" });
let settings = Settings::new()
.with_filterable_attributes(["release_timestamp"]);
let task: TaskInfo = client
.index("games")
.set_settings(&settings)
.await
.unwrap();
client.index("games").updateFilterableAttributes(["release_timestamp"]) { (result) in
switch result {
case .success(let task):
print(task)
case .failure(let error):
print(error)
}
}
await client
.index('games')
.updateFilterableAttributes(['release_timestamp']);
Once you have configured filterableAttributes, you can filter search results by date. The following query only returns games released between 2018 and 2022:
cURL
JS
Python
PHP
Java
Ruby
Go
C#
Rust
Swift
Dart
curl \
-X POST 'MEILISEARCH_URL/indexes/games/search' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data-binary '{
"q": "",
"filter": "release_timestamp >= 1514761200 AND release_timestamp < 1672527600"
}'
client.index('games').search('', {
filter: 'release_timestamp >= 1514761200 AND release_timestamp < 1672527600'
})
client.index('games').search('', {
'filter': 'release_timestamp >= 1514761200 AND release_timestamp < 1672527600'
})
$client->index('games')->search('', [
'filter' => ['release_timestamp >= 1514761200 AND release_timestamp < 1672527600']
]);
SearchRequest searchRequest = SearchRequest.builder().q("").filter(new String[] {"release_timestamp >= 1514761200 AND release_timestamp < 1672527600"}).build();
client.index("games").search(searchRequest);
client.index('games').search('', {
filter: 'release_timestamp >= 1514761200 AND release_timestamp < 1672527600'
})
client.Index("games").Search("", &meilisearch.SearchRequest{
Filter: "release_timestamp >= 1514761200 AND release_timestamp < 1672527600",
})
var filters = new SearchQuery() { Filter = "release_timestamp >= 1514761200 AND release_timestamp < 1672527600" };
var games = await client.Index("games").SearchAsync<Game>("", filters);
let results: SearchResults<Game> = client
.index("games")
.search()
.with_filter("release_timestamp >= 1514761200 AND release_timestamp < 1672527600")
.execute()
.await
.unwrap();
let searchParameters = SearchParameters(
query: "",
filter: "release_timestamp >= 1514761200 AND release_timestamp < 1672527600"
)
client.index("games").search(searchParameters) { (result: Result<Searchable<Game>, Swift.Error>) in
switch result {
case .success(let searchResult):
print(searchResult)
case .failure(let error):
print(error)
}
}
await client.index('games').search(
'',
SearchQuery(
filterExpression: Meili.and([
Meili.gte(
'release_timestamp'.toMeiliAttribute(),
Meili.value(DateTime(2017, 12, 31, 23, 0)),
),
Meili.lt(
'release_timestamp'.toMeiliAttribute(),
Meili.value(DateTime(2022, 12, 31, 23, 0)),
),
]),
),
);
Sorting by date
To sort search results chronologically, add your document’s timestamp field to the list of sortableAttributes:
cURL
JS
Python
PHP
Java
Ruby
Go
C#
Rust
Swift
Dart
curl \
-X PUT 'MEILISEARCH_URL/indexes/games/settings/sortable-attributes' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data-binary '[
"release_timestamp"
]'
client.index('games').updateSortableAttributes(['release_timestamp'])
client.index('games').update_sortable_attributes(['release_timestamp'])
$client->index('games')->updateSortableAttributes(['release_timestamp']);
Settings settings = new Settings();
settings.setSortableAttributes(new String[] {"release_timestamp"});
client.index("games").updateSettings(settings);
client.index('games').update_sortable_attributes(['release_timestamp'])
sortableAttributes := []string{"release_timestamp","author"}
client.Index("games").UpdateSortableAttributes(&sortableAttributes)
await client.Index("games").UpdateSortableAttributesAsync(new string[] { "release_timestamp" });
let settings = Settings::new()
.with_sortable_attributes(["release_timestamp"]);
let task: TaskInfo = client
.index("games")
.set_settings(&settings)
.await
.unwrap();
client.index("games").updateSortableAttributes(["release_timestamp"]) { (result) in
switch result {
case .success(let task):
print(task)
case .failure(let error):
print(error)
}
}
await client
.index('games')
.updateSortableAttributes(['release_timestamp']);
Once you have configured sortableAttributes, you can sort your search results based on their timestamp. The following query returns all games sorted from most recent to oldest:
cURL
JS
Python
PHP
Java
Ruby
Go
C#
Rust
Swift
Dart
curl \
-X POST 'MEILISEARCH_URL/indexes/games/search' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data-binary '{
"q": "",
"sort": ["release_timestamp:desc"]
}'
client.index('games').search('', {
sort: ['release_timestamp:desc'],
})
client.index('games').search('', {
'sort': ['release_timestamp:desc']
})
$client->index('games')->search('', ['sort' => ['release_timestamp:desc']]);
SearchRequest searchRequest = SearchRequest.builder().q("").sort(new String[] {"release_timestamp:desc"}).build();
client.index("games").search(searchRequest);
client.index('games').search('', sort: ['release_timestamp:desc'])
client.Index("games").Search("", &meilisearch.SearchRequest{
Sort: []string{
"release_timestamp:desc",
},
})
SearchQuery sort = new SearchQuery() { Sort = new string[] { "release_timestamp:desc" }};
await client.Index("games").SearchAsync<Game>("", sort);
let results: SearchResults<Game> = client
.index("games")
.search()
.with_sort(["release_timestamp:desc"])
.execute()
.await
.unwrap();
let searchParameters = SearchParameters(
query: "",
sort: ["release_timestamp:desc"],
)
client.index("games").search(searchParameters) { (result: Result<Searchable<Game>, Swift.Error>) in
switch result {
case .success(let searchResult):
print(searchResult)
case .failure(let error):
print(error)
}
}
await client
.index('games')
.search('', SearchQuery(sort: ['release_timestamp:desc']));
Next steps
Combine filters and sort
Use filters and sorting together to narrow and order search results.
Sort results
Configure sortable attributes and sort search results by any field.
Filter expression reference
Learn about all available filter operators and expression syntax.
