Allow flat query expressions
Instead of having to specify [*] or * to get/set/del values in embedded arrays, it now supports access embedded values using a flat style for arrays.
This commit is contained in:
parent
ca6974a5a8
commit
c28057f8ef
3 changed files with 56 additions and 8 deletions
|
@ -25,12 +25,12 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
Value::Object(v) => match p {
|
||||||
Part::Field(p) => match path.parts.len() {
|
Part::Field(f) => match path.parts.len() {
|
||||||
1 => {
|
1 => {
|
||||||
v.remove(&p.name);
|
v.remove(&f.name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => match v.value.get_mut(&p.name) {
|
_ => match v.value.get_mut(&f.name) {
|
||||||
Some(v) if v.is_some() => v.del(ctx, opt, txn, &path.next()).await,
|
Some(v) if v.is_some() => v.del(ctx, opt, txn, &path.next()).await,
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
},
|
},
|
||||||
|
@ -110,6 +110,17 @@ impl Value {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_ => match path.parts.len() {
|
||||||
|
1 => {
|
||||||
|
v.value.clear();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let fut = v.value.iter_mut().map(|v| v.del(&ctx, opt, txn, &path));
|
||||||
|
try_join_all(fut).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
},
|
},
|
||||||
// Ignore everything else
|
// Ignore everything else
|
||||||
|
@ -208,6 +219,16 @@ mod tests {
|
||||||
assert_eq!(res, val);
|
assert_eq!(res, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn del_array_fields_flat() {
|
||||||
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
let idi = Idiom::parse("test.something[*].age");
|
||||||
|
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||||
|
let res = Value::parse("{ test: { something: [{ }, { }] } }");
|
||||||
|
val.del(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||||
|
assert_eq!(res, val);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn del_array_where_field() {
|
async fn del_array_where_field() {
|
||||||
let (ctx, opt, txn) = mock().await;
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
|
|
@ -25,7 +25,7 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
Value::Object(v) => match p {
|
||||||
Part::Field(p) => match v.value.get(&p.name) {
|
Part::Field(f) => match v.value.get(&f.name) {
|
||||||
Some(v) => v.get(ctx, opt, txn, &path.next()).await,
|
Some(v) => v.get(ctx, opt, txn, &path.next()).await,
|
||||||
None => Ok(Value::None),
|
None => Ok(Value::None),
|
||||||
},
|
},
|
||||||
|
@ -60,7 +60,10 @@ impl Value {
|
||||||
}
|
}
|
||||||
Ok(a.into())
|
Ok(a.into())
|
||||||
}
|
}
|
||||||
_ => Ok(Value::None),
|
_ => {
|
||||||
|
let fut = v.value.iter().map(|v| v.get(&ctx, opt, txn, &path));
|
||||||
|
try_join_all(fut).await.map(|v| v.into())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// Current path part is a thing
|
// Current path part is a thing
|
||||||
Value::Thing(v) => match path.parts.len() {
|
Value::Thing(v) => match path.parts.len() {
|
||||||
|
@ -173,6 +176,15 @@ mod tests {
|
||||||
assert_eq!(res, Value::from(vec![34, 36]));
|
assert_eq!(res, Value::from(vec![34, 36]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn get_array_fields_flat() {
|
||||||
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
let idi = Idiom::parse("test.something.age");
|
||||||
|
let val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||||
|
let res = val.get(&ctx, &opt, &txn, &idi).await.unwrap();
|
||||||
|
assert_eq!(res, Value::from(vec![34, 36]));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_array_where_field() {
|
async fn get_array_where_field() {
|
||||||
let (ctx, opt, txn) = mock().await;
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
|
|
@ -24,12 +24,12 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
Value::Object(v) => match p {
|
||||||
Part::Field(p) => match v.value.get_mut(&p.name) {
|
Part::Field(f) => match v.value.get_mut(&f.name) {
|
||||||
Some(v) if v.is_some() => v.set(ctx, opt, txn, &path.next(), val).await,
|
Some(v) if v.is_some() => v.set(ctx, opt, txn, &path.next(), val).await,
|
||||||
_ => {
|
_ => {
|
||||||
let mut obj = Value::base();
|
let mut obj = Value::base();
|
||||||
obj.set(ctx, opt, txn, &path.next(), val).await?;
|
obj.set(ctx, opt, txn, &path.next(), val).await?;
|
||||||
v.insert(&p.name, obj);
|
v.insert(&f.name, obj);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -65,7 +65,12 @@ impl Value {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => {
|
||||||
|
let fut =
|
||||||
|
v.value.iter_mut().map(|v| v.set(ctx, opt, txn, &path, val.clone()));
|
||||||
|
try_join_all(fut).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// Current path part is empty
|
// Current path part is empty
|
||||||
Value::Null => {
|
Value::Null => {
|
||||||
|
@ -206,6 +211,16 @@ mod tests {
|
||||||
assert_eq!(res, val);
|
assert_eq!(res, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn set_array_fields_flat() {
|
||||||
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
let idi = Idiom::parse("test.something.age");
|
||||||
|
let mut val = Value::parse("{ test: { something: [{ age: 34 }, { age: 36 }] } }");
|
||||||
|
let res = Value::parse("{ test: { something: [{ age: 21 }, { age: 21 }] } }");
|
||||||
|
val.set(&ctx, &opt, &txn, &idi, Value::from(21)).await.unwrap();
|
||||||
|
assert_eq!(res, val);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn set_array_where_field() {
|
async fn set_array_where_field() {
|
||||||
let (ctx, opt, txn) = mock().await;
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
|
Loading…
Reference in a new issue