Skip to content

Commit c3b668c

Browse files
committed
Add csv delimiter
1 parent 6a0d5f6 commit c3b668c

File tree

5 files changed

+90
-13
lines changed

5 files changed

+90
-13
lines changed

datasets/songs_custom_delimiter.csv

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
id;title;album;artist;genre;country;released;duration;released-timestamp;duration-float
2+
702481615;Armatage Shanks;Dookie: The Ultimate Critical Review;Green Day;Rock;Europe;2005;;1104537600;
3+
888221515;Old Folks;Six Classic Albums Plus Bonus Tracks;Harold Land;Jazz;Europe;2013;6:36;1356998400;6.36
4+
1382413601;คำขอร้อง;สำเนียงคนจันทร์ / เอาเถอะถ้าเห็นเขาดีกว่า;อิทธิพล บำรุงกุล;"Folk; World; & Country";Thailand;;;;
5+
190889300;Track 1;Summer Breeze;Dreas;Funk / Soul;US;2008;18:56;1199145600;18.56
6+
813645611;Slave (Alternative Version);Honky Château;Elton John;Rock;Europe;;2:53;;2.5300000000000002
7+
394018506;Sex & Geld;Trackz Für Den Index;Mafia Clikk;Hip Hop;Germany;2006;5:02;1136073600;5.02
8+
1522481803;Pisciaunella;Don Pepp U Pacce;Giovanni Russo (2);"Folk; World; & Country";Italy;1980;;315532800;
9+
862296713;不知;Kiss 2001 Hong Kong Live Concert;Various;Electronic;Hong Kong;2002-04-13;;1018656000;
10+
467946423;Rot;Be Quick Or Be Dead Vol. 3;Various;Electronic;Serbia;2013-06-20;1:00;1371686400;1
11+
1323854803;"Simulation Project 1; ツキハナ「Moonflower」";Unlimited Dream Company;Amun Dragoon;Electronic;US;2018-04-10;2:44;1523318400;2.44
12+
235115704;Doctor Vine;The Big F;The Big F;Rock;US;1989;5:29;599616000;5.29
13+
249025232;"Ringel; Ringel; Reihe";Kinderlieder ABC - Der Bielefelder Kinderchor Singt 42 Lieder Von A-Z;Der Bielefelder Kinderchor;Children's;Germany;1971;;31536000;
14+
710094000;Happy Safari = Safari Feliz;Safari Swings Again = El Safari Sigue En Su Swing;Bert Kaempfert & His Orchestra;Jazz;Argentina;1977;2:45;220924800;2.45
15+
538632700;Take Me Up;Spring;Various;Electronic;US;2000;3:06;946684800;3.06
16+
1556505508;Doin To Me ( Radio Version );Say My Name;Netta Dogg;Hip Hop;US;2005;;1104537600;
17+
1067031900;Concerto For Balloon & Orchestra / Concerto For Synthesizer & Orchestra;Concerto For Balloon & Orchestra And Three Overtures;Stanyan String & Wind Ensemble;Classical;US;1977;;220924800;
18+
137251914;"I Love The Nightlife (Disco 'Round) (Real Rapino 7"" Mix)";The Adventures Of Priscilla: Queen Of The Desert - Original Motion Picture Soundtrack;Various;Stage & Screen;US;1994;3:31;757382400;3.31
19+
554983904;Walking On The Moon;Certifiable (Live In Buenos Aires);The Police;Rock;Malaysia;2008-11-00;;1225497600;
20+
557616002;Two Soldiers;Jerry Garcia / David Grisman;David Grisman;"Folk; World; & Country";US;2014-04-00;4:24;1396310400;4.24
21+
878936809;When You Gonna Learn;Live At Firenze 93;Jamiroquai;Funk / Soul;France;2004;13:01;1072915200;13.01

meilisearch/index.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ def add_documents_csv(
434434
self,
435435
str_documents: str,
436436
primary_key: Optional[str] = None,
437+
csv_delimiter: Optional[str] = None,
437438
) -> TaskInfo:
438439
"""Add string documents from a CSV file to the index.
439440
@@ -443,6 +444,8 @@ def add_documents_csv(
443444
String of document from a CSV file.
444445
primary_key (optional):
445446
The primary-key used in index. Ignored if already set up.
447+
csv_delimiter:
448+
One ASCII character used to customize the delimiter for CSV. Comma used by default.
446449
447450
Returns
448451
-------
@@ -455,7 +458,7 @@ def add_documents_csv(
455458
MeilisearchApiError
456459
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://docs.meilisearch.com/errors/#meilisearch-errors
457460
"""
458-
return self.add_documents_raw(str_documents, primary_key, "text/csv")
461+
return self.add_documents_raw(str_documents, primary_key, "text/csv", csv_delimiter)
459462

460463
def add_documents_ndjson(
461464
self,
@@ -489,6 +492,7 @@ def add_documents_raw(
489492
str_documents: str,
490493
primary_key: Optional[str] = None,
491494
content_type: Optional[str] = None,
495+
csv_delimiter: Optional[str] = None,
492496
) -> TaskInfo:
493497
"""Add string documents to the index.
494498
@@ -499,7 +503,10 @@ def add_documents_raw(
499503
primary_key (optional):
500504
The primary-key used in index. Ignored if already set up.
501505
type:
502-
The type of document. Type available: 'csv', 'json', 'jsonl'
506+
The type of document. Type available: 'csv', 'json', 'jsonl'.
507+
csv_delimiter:
508+
One ASCII character used to customize the delimiter for CSV.
509+
Note: The csv delimiter can only be used with the Content-Type text/csv.
503510
504511
Returns
505512
-------
@@ -512,7 +519,7 @@ def add_documents_raw(
512519
MeilisearchApiError
513520
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://docs.meilisearch.com/errors/#meilisearch-errors
514521
"""
515-
url = self._build_url(primary_key)
522+
url = self._build_url(primary_key=primary_key, csv_delimiter=csv_delimiter)
516523
response = self.http.post(url, str_documents, content_type)
517524
return TaskInfo(**response)
518525

@@ -601,6 +608,7 @@ def update_documents_csv(
601608
self,
602609
str_documents: str,
603610
primary_key: Optional[str] = None,
611+
csv_delimiter: Optional[str] = None,
604612
) -> TaskInfo:
605613
"""Update documents as a csv string in the index.
606614
@@ -609,7 +617,9 @@ def update_documents_csv(
609617
str_documents:
610618
String of document from a CSV file.
611619
primary_key (optional):
612-
The primary-key used in index. Ignored if already set up
620+
The primary-key used in index. Ignored if already set up.
621+
csv_delimiter:
622+
One ASCII character used to customize the delimiter for CSV. Comma used by default.
613623
614624
Returns
615625
-------
@@ -622,13 +632,14 @@ def update_documents_csv(
622632
MeilisearchApiError
623633
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://docs.meilisearch.com/errors/#meilisearch-errors
624634
"""
625-
return self.update_documents_raw(str_documents, primary_key, "text/csv")
635+
return self.update_documents_raw(str_documents, primary_key, "text/csv", csv_delimiter)
626636

627637
def update_documents_raw(
628638
self,
629639
str_documents: str,
630640
primary_key: Optional[str] = None,
631641
content_type: Optional[str] = None,
642+
csv_delimiter: Optional[str] = None,
632643
) -> TaskInfo:
633644
"""Update documents as a string in the index.
634645
@@ -640,6 +651,9 @@ def update_documents_raw(
640651
The primary-key used in index. Ignored if already set up.
641652
type:
642653
The type of document. Type available: 'csv', 'json', 'jsonl'
654+
csv_delimiter:
655+
One ASCII character used to customize the delimiter for CSV.
656+
Note: The csv delimiter can only be used with the Content-Type text/csv.
643657
644658
Returns
645659
-------
@@ -652,7 +666,7 @@ def update_documents_raw(
652666
MeilisearchApiError
653667
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://docs.meilisearch.com/errors/#meilisearch-errors
654668
"""
655-
url = self._build_url(primary_key)
669+
url = self._build_url(primary_key=primary_key, csv_delimiter=csv_delimiter)
656670
response = self.http.put(url, str_documents, content_type)
657671
return TaskInfo(**response)
658672

@@ -1530,8 +1544,13 @@ def __settings_url_for(self, sub_route: str) -> str:
15301544
def _build_url(
15311545
self,
15321546
primary_key: Optional[str] = None,
1547+
csv_delimiter: Optional[str] = None,
15331548
) -> str:
1534-
if primary_key is None:
1549+
parameters = {}
1550+
if primary_key:
1551+
parameters["primaryKey"] = primary_key
1552+
if csv_delimiter:
1553+
parameters["csvDelimiter"] = csv_delimiter
1554+
if primary_key is None and csv_delimiter is None:
15351555
return f"{self.config.paths.index}/{self.uid}/{self.config.paths.document}"
1536-
primary_key = parse.urlencode({"primaryKey": primary_key})
1537-
return f"{self.config.paths.index}/{self.uid}/{self.config.paths.document}?{primary_key}"
1556+
return f"{self.config.paths.index}/{self.uid}/{self.config.paths.document}?{parse.urlencode(parameters)}"

tests/conftest.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,25 @@ def small_movies_json_file():
7070
@fixture(scope="session")
7171
def songs_csv():
7272
"""
73-
Runs once per session. Provides the content of songs.csv from read..
73+
Runs once per session. Provides the content of songs.csv from read.
7474
"""
7575
with open("./datasets/songs.csv", encoding="utf-8") as song_csv_file:
7676
return song_csv_file.read().encode("utf-8")
7777

7878

79+
@fixture(scope="session")
80+
def songs_csv_custom_separator():
81+
"""
82+
Runs once per session. Provides the content of songs_custom_delimiter.csv from read.
83+
"""
84+
with open("./datasets/songs_custom_delimiter.csv", encoding="utf-8") as song_csv_file:
85+
return song_csv_file.read().encode("utf-8")
86+
87+
7988
@fixture(scope="session")
8089
def songs_ndjson():
8190
"""
82-
Runs once per session. Provides the content of songs.ndjson from read..
91+
Runs once per session. Provides the content of songs.ndjson from read.
8392
"""
8493
with open("./datasets/songs.ndjson", encoding="utf-8") as song_ndjson_file:
8594
return song_ndjson_file.read().encode("utf-8")

tests/index/test_index_document_meilisearch.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,20 @@ def test_add_documents_csv(empty_index, songs_csv):
197197
assert index.get_primary_key() == "id"
198198

199199

200+
def test_add_documents_csv_with_delimiter(empty_index, songs_csv_custom_separator):
201+
"""Tests adding new documents to a clean index."""
202+
index = empty_index("csv-delimiter")
203+
response = index.add_documents_csv(songs_csv_custom_separator, csv_delimiter=";")
204+
assert isinstance(response, TaskInfo)
205+
assert response.task_uid is not None
206+
task = index.wait_for_task(response.task_uid)
207+
assert task.status == "succeeded"
208+
assert task.details["receivedDocuments"] == 20
209+
documents = index.get_documents().results
210+
assert documents[1].country == "Europe"
211+
assert documents[4].artist == "Elton John"
212+
213+
200214
def test_update_documents_csv(index_with_documents, songs_csv):
201215
"""Tests updating a single document with csv string."""
202216
index = index_with_documents()
@@ -208,6 +222,20 @@ def test_update_documents_csv(index_with_documents, songs_csv):
208222
assert index.get_primary_key() == "id"
209223

210224

225+
def test_update_documents_csv_with_delimiter(index_with_documents, songs_csv_custom_separator):
226+
"""Tests adding new documents to a clean index."""
227+
index = index_with_documents()
228+
response = index.update_documents_csv(songs_csv_custom_separator, csv_delimiter=";")
229+
assert isinstance(response, TaskInfo)
230+
assert response.task_uid is not None
231+
task = index.wait_for_task(response.task_uid)
232+
assert task.status == "succeeded"
233+
assert task.details["receivedDocuments"] == 20
234+
document = index.get_document("813645611")
235+
assert document.country == "Europe"
236+
assert document.artist == "Elton John"
237+
238+
211239
def test_add_documents_json(empty_index, small_movies_json_file):
212240
"""Tests adding new documents to a clean index."""
213241
index = empty_index()

tests/index/test_index_search_meilisearch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
def test_basic_search(index_with_documents):
5-
"""Tests search with an simple query."""
5+
"""Tests search with a simple query."""
66
response = index_with_documents().search("How to Train Your Dragon")
77
assert isinstance(response, dict)
88
assert response["hits"][0]["id"] == "166428"
@@ -356,7 +356,7 @@ def test_phrase_search(index_with_documents):
356356

357357

358358
def test_basic_search_on_nested_documents(index_with_documents, nested_movies):
359-
"""Tests search with an simple query on nested fields."""
359+
"""Tests search with a simple query on nested fields."""
360360
response = index_with_documents("nested_fields_index", nested_movies).search("An awesome")
361361
assert isinstance(response, dict)
362362
assert response["hits"][0]["id"] == 5

0 commit comments

Comments
 (0)