Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] has operation on stored elements #295

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions conformance/tests/ot_has.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,23 @@ def test_has_eq(man):
return errors


def test_has_prev(man):
errors = []
G = man.setGraph("swapi")

q = G.query().V().hasLabel("Character").as_("1").out("homeworld").out("residents")
q = q.has(gripql.neq("$1._gid", "$._gid"))
count = 0
for i in q.render(["$1._gid", "$._gid"]):
print(i)
if i[0] == i[1]:
errors.append("History based filter failed: %s" % (i[0]) )
count += 1
if count < 10:
errors.append("Not enough elements found: %d" % (count))
return errors


def test_has_neq(man):
errors = []

Expand Down
39 changes: 34 additions & 5 deletions conformance/tests/ot_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,67 @@ def test_render(man):

G = man.setGraph("swapi")

query = G.query().V().hasLabel("Person").render(
query = G.query().V().hasLabel("Character").render(
{
"Name": "name",
"Age": "age"
}
)
count = 0
for row in query:
count += 1
if 'Age' not in row or "Name" not in row:
errors.append("Missing fields")

query = G.query().V().hasLabel("Person").render(
if count != 18:
errors.append("Incorrect number of rows returned")
query = G.query().V().hasLabel("Character").render(
{
"Name": "name",
"NonExistent": "non-existent"
}
)
count = 0
for row in query:
count += 1
if 'NonExistent' not in row or "Name" not in row:
errors.append("Missing fields")
if count != 18:
errors.append("Incorrect number of rows returned")

query = G.query().V().hasLabel("Person").render(["name", "age"])
query = G.query().V().hasLabel("Character").render(["name", "age"])
for row in query:
count += 1
if not isinstance(row, list):
errors.append("unexpected output format")
if len(row) != 2:
errors.append("Missing fields")

query = G.query().V().hasLabel("Person").render(["name", "non-existent"])
query = G.query().V().hasLabel("Character").render(["name", "non-existent"])
for row in query:
if not isinstance(row, list):
errors.append("unexpected output format")
if len(row) != 2:
errors.append("Missing fields")

return errors


def test_render_mark(man):
"""
test_render_mark check if various mark symbols are recalled correctly
"""
errors = []

G = man.setGraph("swapi")

query = G.query().V().hasLabel("Character").as_("char").out("starships").render(["$char.name", "$._gid", "$"])
for row in query:
if not isinstance(row[0], str):
errors.append("incorrect return type: %s", row[0])
if '_gid' not in row[2]:
errors.append("incorrect return type: %s", row[2])
if '_label' not in row[2]:
errors.append("incorrect return type: %s", row[2])
#print(row)

return errors
8 changes: 8 additions & 0 deletions engine/logic/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logic

import (
"reflect"
"strings"

"github.com/spf13/cast"

Expand All @@ -17,6 +18,13 @@ func MatchesCondition(trav gdbi.Traveler, cond *gripql.HasCondition) bool {
val = gdbi.TravelerPathLookup(trav, cond.Key)
condVal = cond.Value.AsInterface()

if condValStr, ok := condVal.(string); ok {
if strings.HasPrefix(condValStr, "$.") {
//log.Infof("condVal: %s\n", condValStr)
condVal = gdbi.TravelerPathLookup(trav, condValStr)
}
//TODO: Add escape for $ user string
}
//If filtering on nil or no match was found on float64 casting operators return false
log.Debug("val: ", val, "condVal: ", condVal)
if (val == nil || condVal == nil) &&
Expand Down
3 changes: 3 additions & 0 deletions mongo/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,9 @@ func (comp *Compiler) Compile(stmts []*gripql.GraphStatement, opts *gdbi.Compile
}
}

//queryStr, _ := json.MarshalIndent(query, "", " ")
//log.Infof("Mongo query pipeline: %s", queryStr)

// query must be less than 16MB limit
bsonSize, err := bson.Marshal(bson.M{"pipeline": query})
if err != nil {
Expand Down
31 changes: 27 additions & 4 deletions mongo/has_evaluator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mongo

import (
"fmt"
"strings"

"github.com/bmeg/grip/gripql"
"github.com/bmeg/grip/log"
Expand All @@ -22,7 +22,7 @@ func convertHasExpression(stmt *gripql.HasExpression, not bool) bson.M {
} else {
key := cond.Key
output = convertHasExpression(gripql.And(gripql.Gt(key, lims[0]), gripql.Lt(key, lims[1])), not)
fmt.Printf("inside: %#v\n", output)
//fmt.Printf("inside: %#v\n", output)
}

case gripql.Condition_OUTSIDE:
Expand Down Expand Up @@ -88,12 +88,32 @@ func convertCondition(cond *gripql.HasCondition, not bool) bson.M {
key = ToPipelinePath(cond.Key)
val = cond.Value.AsInterface()

isExpr := false

if valStr, ok := val.(string); ok {
if strings.HasPrefix(valStr, "$") {
val = "$" + ToPipelinePath(valStr)
isExpr = true
}
log.Infof("mongo val str: %s(%s) -- %s(%s)", cond.Key, key, valStr, val)
}
expr := bson.M{}
switch cond.Condition {
case gripql.Condition_EQ:
expr = bson.M{"$eq": val}
if isExpr {
//expr = bson.M{"$expr": bson.M{"$eq": []any{"$" + key, val}}}
expr = bson.M{"$eq": []any{bson.M{"$getField": key}, val}}
} else {
expr = bson.M{"$eq": val}
}
case gripql.Condition_NEQ:
expr = bson.M{"$ne": val}
if isExpr {
//expr = bson.M{"$expr": bson.M{"$ne": []any{"$" + key, val}}}
expr = bson.M{"$ne": []any{bson.M{"$getField": key}, val}}
log.Infof("filter struct: %#v", expr)
} else {
expr = bson.M{"$ne": val}
}
case gripql.Condition_GT:
expr = bson.M{"$gt": val}
case gripql.Condition_GTE:
Expand All @@ -114,5 +134,8 @@ func convertCondition(cond *gripql.HasCondition, not bool) bson.M {
if not {
return bson.M{key: bson.M{"$not": expr}}
}
if isExpr {
return expr
}
return bson.M{key: expr}
}
7 changes: 5 additions & 2 deletions mongo/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mongo
import (
//"fmt"
"context"
"encoding/json"
"strconv"
"strings"

Expand Down Expand Up @@ -52,7 +53,9 @@ func getDataElement(result map[string]interface{}) *gdbi.DataElement {

// Process runs the mongo aggregation pipeline
func (proc *Processor) Process(ctx context.Context, man gdbi.Manager, in gdbi.InPipe, out gdbi.OutPipe) context.Context {
plog := log.WithFields(log.Fields{"query_id": util.UUID(), "query": proc.query, "query_collection": proc.startCollection})
queryStr, _ := json.MarshalIndent(proc.query, "", " ")
//queryStr, _ := bson.MarshalExtJSON(proc.query, false, false)
plog := log.WithFields(log.Fields{"query_id": util.UUID(), "query": string(queryStr), "query_collection": proc.startCollection})
plog.Debug("Running Mongo Processor")

go func() {
Expand All @@ -65,7 +68,7 @@ func (proc *Processor) Process(ctx context.Context, man gdbi.Manager, in gdbi.In
trueVal := true
cursor, err := initCol.Aggregate(ctx, proc.query, &options.AggregateOptions{AllowDiskUse: &trueVal})
if err != nil {
plog.Errorf("Query Error (%s) : %s", proc.query, err)
plog.Errorf("Query Error: %s", err)
continue
}
//defer cursor.Close(context.TODO())
Expand Down
Loading