wolf4ood/gremlin-rs

Cardinality Support?

criminosis opened this issue · 3 comments

This Cardinality to be clear

Right now it there doesn't seem to be deriving elements that are Vec<T> or HashSet<T> on structs as in stuff like Vec<String> or a HashSet<String>.

I was able to prove out something that appears to work with these:


fn for_list<T>(glist: List) -> GremlinResult<Vec<T>>
where
    T: std::convert::TryFrom<GValue, Error = GremlinError>,
{
    glist
        .take()
        .into_iter()
        .map(|x| x.try_into())
        .collect::<GremlinResult<Vec<T>>>()
}

fn for_list_to_set<T>(glist: List) -> GremlinResult<HashSet<T>>
where
    T: std::convert::TryFrom<GValue, Error = GremlinError> + Hash + Eq,
{
    glist
        .take()
        .into_iter()
        .map(|x| x.try_into())
        .collect::<GremlinResult<HashSet<T>>>()
}

fn for_set<T>(gset: Set) -> GremlinResult<HashSet<T>>
where
    T: std::convert::TryFrom<GValue, Error = GremlinError> + Hash + Eq,
{
    gset.take()
        .into_iter()
        .map(|x| x.try_into())
        .collect::<GremlinResult<HashSet<T>>>()
}


macro_rules! impl_try_from_set {
    ($t:ty) => {
        impl std::convert::TryFrom<GValue> for HashSet<$t> {
            type Error = crate::GremlinError;

            fn try_from(value: GValue) -> GremlinResult<Self> {
                match value {
                    GValue::List(s) => for_list_to_set(s),
                    GValue::Set(s) => for_set(s),
                    _ => Err(GremlinError::Cast(format!(
                        "Cannot cast {:?} to Set",
                        value
                    ))),
                }
            }
        }
    };
}

impl_try_from_set!(String);
impl_try_from_set!(i32);
impl_try_from_set!(i64);

macro_rules! impl_try_from_list {
    ($t:ty) => {
        impl std::convert::TryFrom<GValue> for Vec<$t> {
            type Error = crate::GremlinError;

            fn try_from(value: GValue) -> GremlinResult<Self> {
                match value {
                    GValue::List(s) => for_list(s),
                    _ => Err(GremlinError::Cast(format!(
                        "Cannot cast {:?} to Vec",
                        value
                    ))),
                }
            }
        }
    };
}

impl_try_from_list!(String);
impl_try_from_list!(i32);
impl_try_from_list!(i64);

I could do another PR if there's interest in incorporating these. FWIW I was somewhat confused though by the logic here:

1 => vec.pop().unwrap().try_into(),

Seems like we shouldn't be attempting to parse List properties there? Maybe the PR should also remove that logic?

The main issue that I see with cardinality and multivalue properties for vertices is that they can contains different type for a key. So in case if your output is vec hashset of T you could not represent the different types

Probably the best way to approach this is to try to convert the multi-properties with tuples instead of vec or set. But in case o have to check more on this :)

that they can contains different type for a key

Could you elaborate @wolf4ood? I wouldn't expect that to be permitted. Like if you have a property of "names" and insert multiple values that would seem to forced to being String values due to the schema. Like here's a demonstration of what I mean. Even when I inserted an integer value 1234 (notice the lack of ' it when I inserted it) it coerced it into being a string to confirm to the type defined in the schema.

gremlin> g.addV('person').property(list, 'names', 'chris')
==>v[4168]
gremlin> g.V(4168).property('names', 'chris2')
==>v[4168]
gremlin> g.V(4168).valueMap()
==>{names=[chris, chris2]}
gremlin> g.V(4168).property('names', 1234)
==>v[4168]
gremlin> g.V(4168).valueMap()
==>{names=[chris, chris2, 1234]}

And then later when doing it for an integer property it rejected when I tried to insert a string:

gremlin> g.V(4168).property(set, 'numbers', 1234)
==>v[4168]
gremlin> g.V(4168).property(set, 'numbers', 589)
==>v[4168]
gremlin> g.V(4168).property(set, 'numbers', 'hello world')
Value [hello world] is not an instance of the expected data type for property key [numbers] and cannot be converted. Expected: class java.lang.Integer, found: class java.lang.String
Type ':help' or ':h' for help.
Display stack trace? [yN]n

Schema below:

gremlin> graph.openManagement().printSchema()
==>------------------------------------------------------------------------------------------------
Vertex Label Name              | Partitioned | Static                                             |
---------------------------------------------------------------------------------------------------
person                         | false       | false                                              |
---------------------------------------------------------------------------------------------------
Edge Label Name                | Directed    | Unidirected | Multiplicity                         |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Property Key Name              | Cardinality | Data Type                                          |
---------------------------------------------------------------------------------------------------
names                          | LIST        | class java.lang.String                             |
numbers                        | SET         | class java.lang.Integer                            |
---------------------------------------------------------------------------------------------------
Vertex Index Name              | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Edge Index (VCI) Name          | Type        | Unique    | Backing        | Key:           Status |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
Relation Index                 | Type        | Direction | Sort Key       | Order    |     Status |
---------------------------------------------------------------------------------------------------

Admittedly this from using a JanusGraph setup