@@ -5,7 +5,7 @@ use std::{fs, thread};
5
5
6
6
use anyhow:: Context ;
7
7
use byte_unit:: Byte ;
8
- use clap:: Parser ;
8
+ use clap:: { Parser , ValueEnum } ;
9
9
use exponential_backoff:: Backoff ;
10
10
use flate2:: write:: GzEncoder ;
11
11
use flate2:: Compression ;
@@ -44,7 +44,7 @@ struct Opt {
44
44
api_key : Option < String > ,
45
45
46
46
/// A list of file paths that are streamed and sent to Meilisearch in batches.
47
- #[ structopt( long) ]
47
+ #[ structopt( long, num_args ( 1 .. ) ) ]
48
48
files : Vec < PathBuf > ,
49
49
50
50
/// The size of the batches sent to Meilisearch.
@@ -54,11 +54,28 @@ struct Opt {
54
54
/// The number of batches to skip. Useful when the upload stopped for some reason.
55
55
#[ structopt( long) ]
56
56
skip_batches : Option < u64 > ,
57
+
58
+ /// The operation to perform when uploading a document.
59
+ #[ arg(
60
+ long,
61
+ value_name = "OPERATION" ,
62
+ num_args = 0 ..=1 ,
63
+ default_value_t = DocumentOperation :: AddOrReplace ,
64
+ value_enum
65
+ ) ]
66
+ upload_operation : DocumentOperation ,
67
+ }
68
+
69
+ #[ derive( ValueEnum , Copy , Clone , Debug , PartialEq , Eq ) ]
70
+ enum DocumentOperation {
71
+ AddOrReplace ,
72
+ AddOrUpdate ,
57
73
}
58
74
59
75
fn send_data (
60
76
opt : & Opt ,
61
77
agent : & Agent ,
78
+ upload_operation : DocumentOperation ,
62
79
pb : & ProgressBar ,
63
80
mime : & Mime ,
64
81
data : & [ u8 ] ,
@@ -79,7 +96,10 @@ fn send_data(
79
96
let backoff = Backoff :: new ( retries, min, max) ;
80
97
81
98
for ( attempt, duration) in backoff. into_iter ( ) . enumerate ( ) {
82
- let mut request = agent. post ( & url) ;
99
+ let mut request = match upload_operation {
100
+ DocumentOperation :: AddOrReplace => agent. post ( & url) ,
101
+ DocumentOperation :: AddOrUpdate => agent. put ( & url) ,
102
+ } ;
83
103
request = request. set ( "Content-Type" , mime. as_str ( ) ) ;
84
104
request = request. set ( "Content-Encoding" , "gzip" ) ;
85
105
request = request. set ( "X-Meilisearch-Client" , "Meilisearch Importer" ) ;
@@ -128,22 +148,22 @@ fn main() -> anyhow::Result<()> {
128
148
Mime :: Json => {
129
149
if opt. skip_batches . zip ( pb. length ( ) ) . map_or ( true , |( s, l) | s > l) {
130
150
let data = fs:: read_to_string ( file) ?;
131
- send_data ( & opt, & agent, & pb, & mime, data. as_bytes ( ) ) ?;
151
+ send_data ( & opt, & agent, opt . upload_operation , & pb, & mime, data. as_bytes ( ) ) ?;
132
152
}
133
153
pb. inc ( 1 ) ;
134
154
}
135
155
Mime :: NdJson => {
136
156
for chunk in nd_json:: NdJsonChunker :: new ( file, size) {
137
157
if opt. skip_batches . zip ( pb. length ( ) ) . map_or ( true , |( s, l) | s > l) {
138
- send_data ( & opt, & agent, & pb, & mime, & chunk) ?;
158
+ send_data ( & opt, & agent, opt . upload_operation , & pb, & mime, & chunk) ?;
139
159
}
140
160
pb. inc ( 1 ) ;
141
161
}
142
162
}
143
163
Mime :: Csv => {
144
164
for chunk in csv:: CsvChunker :: new ( file, size) {
145
165
if opt. skip_batches . zip ( pb. length ( ) ) . map_or ( true , |( s, l) | s > l) {
146
- send_data ( & opt, & agent, & pb, & mime, & chunk) ?;
166
+ send_data ( & opt, & agent, opt . upload_operation , & pb, & mime, & chunk) ?;
147
167
}
148
168
pb. inc ( 1 ) ;
149
169
}
0 commit comments