func populateGraph(t *testing.T) (string, string, *store.Store) { // logrus.SetLevel(logrus.DebugLevel) dir, err := ioutil.TempDir("", "storetest_") require.NoError(t, err) ps, err := store.NewStore(dir) require.NoError(t, err) schema.ParseBytes([]byte(schemaStr)) posting.Init(ps) worker.Init(ps) group.ParseGroupConfig("") dir2, err := ioutil.TempDir("", "wal_") require.NoError(t, err) worker.StartRaftNodes(dir2) // So, user we're interested in has uid: 1. // She has 5 friends: 23, 24, 25, 31, and 101 addEdgeToUID(t, ps, "friend", 1, 23) addEdgeToUID(t, ps, "friend", 1, 24) addEdgeToUID(t, ps, "friend", 1, 25) addEdgeToUID(t, ps, "friend", 1, 31) addEdgeToUID(t, ps, "friend", 1, 101) // Now let's add a few properties for the main user. addEdgeToValue(t, ps, "name", 1, "Michonne") addEdgeToValue(t, ps, "gender", 1, "female") var coord types.Geo err = coord.UnmarshalText([]byte("{\"Type\":\"Point\", \"Coordinates\":[1.1,2.0]}")) require.NoError(t, err) gData, err := coord.MarshalBinary() require.NoError(t, err) addEdgeToTypedValue(t, ps, "loc", 1, types.GeoID, gData) data, err := types.Int32(15).MarshalBinary() require.NoError(t, err) addEdgeToTypedValue(t, ps, "age", 1, types.Int32ID, data) addEdgeToValue(t, ps, "address", 1, "31, 32 street, Jupiter") data, err = types.Bool(true).MarshalBinary() require.NoError(t, err) addEdgeToTypedValue(t, ps, "alive", 1, types.BoolID, data) addEdgeToValue(t, ps, "age", 1, "38") addEdgeToValue(t, ps, "survival_rate", 1, "98.99") addEdgeToValue(t, ps, "sword_present", 1, "true") addEdgeToValue(t, ps, "_xid_", 1, "mich") // Now let's add a name for each of the friends, except 101. addEdgeToTypedValue(t, ps, "name", 23, types.StringID, []byte("Rick Grimes")) addEdgeToValue(t, ps, "age", 23, "15") err = coord.UnmarshalText([]byte(`{"Type":"Polygon", "Coordinates":[[[0.0,0.0], [2.0,0.0], [2.0, 2.0], [0.0, 2.0]]]}`)) require.NoError(t, err) gData, err = coord.MarshalBinary() require.NoError(t, err) addEdgeToTypedValue(t, ps, "loc", 23, types.GeoID, gData) addEdgeToValue(t, ps, "address", 23, "21, mark street, Mars") addEdgeToValue(t, ps, "name", 24, "Glenn Rhee") addEdgeToValue(t, ps, "name", 25, "Daryl Dixon") addEdgeToValue(t, ps, "name", 31, "Andrea") addEdgeToValue(t, ps, "dob", 23, "1910-01-02") addEdgeToValue(t, ps, "dob", 24, "1909-05-05") addEdgeToValue(t, ps, "dob", 25, "1909-01-10") addEdgeToValue(t, ps, "dob", 31, "1901-01-15") return dir, dir2, ps }
// queryTokens returns the tokens to be used to look up the geo index for a given filter. func queryTokens(qt QueryType, data string, maxDistance float64) ([]string, *QueryData, error) { // Try to parse the data as geo type. var g types.Geo geoData := strings.Replace(data, "'", "\"", -1) err := g.UnmarshalText([]byte(geoData)) if err != nil { return nil, nil, x.Wrapf(err, "Cannot decode given geoJson input") } var l *s2.Loop var pt *s2.Point switch v := g.T.(type) { case *geom.Point: p := pointFromPoint(v) pt = &p case *geom.Polygon: l, err = loopFromPolygon(v) if err != nil { return nil, nil, err } default: return nil, nil, x.Errorf("Cannot query using a geometry of type %T", v) } x.AssertTruef(l != nil || pt != nil, "We should have a point or a loop.") parents, cover, err := indexCells(g) if err != nil { return nil, nil, err } switch qt { case QueryTypeWithin: // For a within query we only need to look at the objects whose parents match our cover. // So we take our cover and prefix with the parentPrefix to look in the index. toks := toTokens(cover, parentPrefix) return toks, &QueryData{pt: pt, loop: l, qtype: qt}, nil case QueryTypeContains: if l != nil { return nil, nil, x.Errorf("Cannot use a polygon in a contains query") } // For a contains query, we only need to look at the objects whose cover matches our // parents. So we take our parents and prefix with the coverPrefix to look in the index. return toTokens(parents, coverPrefix), &QueryData{pt: pt, qtype: qt}, nil case QueryTypeNear: if l != nil { return nil, nil, x.Errorf("Cannot use a polygon in a near query") } return nearQueryKeys(*pt, maxDistance) case QueryTypeIntersects: // An intersects query is essentially the union of contains and within. So we look at all // the objects whose parents match our cover as well as all the objects whose cover matches // our parents. toks := parentCoverTokens(parents, cover) return toks, &QueryData{pt: pt, loop: l, qtype: qt}, nil default: return nil, nil, x.Errorf("Unknown query type") } }