I'm asking nearly the same question as you see here, but with the constraint that the groovy, not java, syntax must be used. Ideally the answer to would be very concise.
I have a simple graph of people vertices. Each has an "age" property listing that person's age in years. There are also "worksFor" labeled edges connecting pairs of people vertices. I'd like to see all edges where the people at both ends of the edge have the same age property.
I'd then like a similar query where the two ages differ by less than 3 years.
As mentioned, this should be in groovy, not Java, syntax. Gremlin 3 is preferred, but Gremlin 2 answers are acceptable.
all edges where the people at both ends of the edge have the same age property
g.V().as("a").outE("worksFor").as("e").inV().as("b").select("a","b").by("age").
where("a", eq("b")).select("e")
where the two ages differ by less than 3 years
g.V().as("a").outE("worksFor").as("e").inV().as("b").select("a","b").by("age").
filter {Math.abs(it.get().get("a") - it.get().get("b")) < 3}.select("e")
If we know the target vertex against which all other vertices are compared, the following may work:
t=g.V().has('id', 'target_node_id').values('age').next()
g.V().has('age').filter{it.get().value('age')-t<=3 && it.get().value('age')-t>=-3}
I don't know how to do it in one query. I also don't know if there is a function/step to get the absolute value.
This only partially satisfies your need, but it may be a start.
Comparing two date properties using math step:
g.V().hasLabel('EnterExitDate').limit(10000).as('enter','exit')
.where("enter",lt("exit")).by('enter').by('exit')
.where(math('(exit - enter) / (3600*1000) ')
.by(values('exit').map({ it.get().time }))
.by(values('enter').map({ it.get().time }))
.is(lt(1)))
.valueMap()
This query will find all pairs of enter-exit record of employees that have happened within 1 hour.
EnterExitDate class:
public class EnterExitDate {
private Date enter;
private Date exit;
// getters and setters...
}
Related
It seems to be a simple question but I have a hard time to find an answer to it. I already have a project with several parameters (project and database parameters). I would like to obtain the LCA results for several scenarios with my parameters having different values each time. I was thinking of the following simple procedure:
change the parameters' value,
update the exchanges in my project,
calculate the LCA results.
I know that the answer should be in the documentation somewhere, but I have a hard time to understand how I should apply it to my ProjectParameters, DatabaseParameters and ActivityParameters.
Thanks in advance!
EDIT: Thanks to #Nabla, I was able to come up with this:
For ProjectParameter
for pjparam in ProjectParameter.select():
if pjparam.name=='my_param_name':
break
pjparam.amount = 3
pjparam.save()
bw.parameters.recalculate()
For DatabaseParameter
for dbparam in DatabaseParameter.select():
if dbparam.name=='my_param_name':
break
dbparam.amount = 3
dbparam.save()
bw.parameters.recalculate()
For ActivityParameter
for param in ActivityParameter.select():
if param.name=='my_param_name':
break
param.amount = 3
param.save()
param.recalculate_exchanges(param.group)
You could import DatabaseParameter and ActivityParameter iterate until you find the parameter you want to change, update the value, save it and recalculate the exchanges. I think you need to do it in tiers. First you update the project parameters (if any) then the database parameters that may depend on project parameters and then the activity parameters that depend on them.
A simplified case without project parameters:
from bw2data.parameters import ActivityParameter,DatabaseParameter
# find the database parameter to be updated
for dbparam in DatabaseParameter.select():
if (dbparam.database == uncertain_db.name) and (dbparam.name=='foo'):
break
dbparam.amount = 3
dbparam.save()
#there is also this method if foruma depend on something else
#dbparam.recalculate(uncertain_db.name)
# here updating the exchanges of a particular activity (act)
for param in ActivityParameter.select():
if param.group == ":".join(act.key):
param.recalculate_exchanges(param.group)
you may want to update all the activities in the project instead of a single one like in the example. you just need to change the condition when looping through the activity parameters.
I have a type ORM query that returns five columns. I just want the company column returned but I need to select all five columns to generate the correct response.
Is there a way to wrap my query in another select statement or transform the results to just get the company column I want?
See my code below:
This is what the query returns currently:
https://i.stack.imgur.com/MghEJ.png
I want it to return:
https://i.stack.imgur.com/qkXJK.png
const qb = createQueryBuilder(Entity, 'stats_table');
qb.select('stats_table.company', 'company');
qb.addSelect('stats_table.title', 'title');
qb.addSelect('city_code');
qb.addSelect('country_code');
qb.addSelect('SUM(count)', 'sum');
qb.where('city_code IS NOT NULL OR country_code IS NOT NULL');
qb.addGroupBy('company');
qb.addGroupBy('stats_table.title');
qb.addGroupBy('country_code');
qb.addGroupBy('city_code');
qb.addOrderBy('sum', 'DESC');
qb.addOrderBy('company');
qb.addOrderBy('title');
qb.limit(3);
qb.cache(true);
return qb.getRawMany();
};```
[1]: https://i.stack.imgur.com/MghEJ.png
[2]: https://i.stack.imgur.com/qkXJK.png
TypeORM didn't meet my criteria, so I'm not experienced with it, but as long as it doesn't cause problems with TypeORM, I see an easy SQL solution and an almost as easy TypeScript solution.
The SQL solution is to simply not select the undesired columns. SQL will allow you to use fields you did not select in WHERE, GROUP BY, and/or ORDER BY clauses, though obviously you'll need to use 'SUM(count)' instead of 'sum' for the order. I have encountered some ORMs that are not happy with this though.
The TS solution is to map the return from qb.getRawMany() so that you only have the field you're interested in. Assuming getRawMany() is returning an array of objects, that would look something like this:
getRawMany().map(companyRecord => {return {company: companyRecord.company}});
That may not be exactly correct, I've taken the day off precisely because I'm sick and my brain is fuzzy enough I was making too many stupid mistakes, but the concept should work even if the code itself doesn't.
EDIT: Also note that map returns a new array, it does not modify the existing array, so you would use this in place of the getRawMany() when assigning, not after the assignment.
guys! I am new to gremlin and I need a help.
I want to understand if there a way to do aggregation on the full graph per node based on values in the neighbors properties?
Example:
I want to calculate mean amount of money spent by a "known" customers.
My graph structure is next:
Customer1 -- > Phone_Number < -- Customer2.
So i want to get, as result, next:
Customer1 Mean(Neighbors.value('money'))
Customer2 Mean(Neighbors.value('money'))
...
The neighbors for a customer(base node) is all other customers (except himself) connected to one(or more) phones associated to base node.
I understand how to exclude base node if I know ID, but is there a way to do calculations across the full graph automatically excluding "starting" nodes?
Like, ignore CustomerK if we start from CustomerK along the all path?
Another small question: Is there a way to filter vertex properties in path by starting vertex value? Like, ignore all customers that older than "age" of starting vertex
You can filter your start vertex by using the step as and then the neq predicate.
like this:
g.V().hasLabel('Customer').as('V').
project('name', 'mean').by('name').by(out().
in().where(neq('V')).dedup().values('money').
mean())
example: https://gremlify.com/as
For filter by properties you can do something similar to this: where(gt('V')).by('age').
g.V().hasLabel('Customer').as('V').
project('name', 'mean').by('name').
by(coalesce(
out().in().where(neq('V')).where(gt('V')).
by('age').
dedup().values('money').mean(),
constant('no values')
))
Neptune 1.0.2.1 + Gremlin + nodejs.
I have a vertext and property, e.g. Vertex - Device, property - Test, the Test property could store different type of data, e.g. number and string
Vertex 1 - Test = ['ABCD','xyz']
Vertex 2 - Test = [123,'XYZ']
I want to do a 'containing' search, e.g. Test=A, or Test=123 regardless the datatype.
I was trying
queryText = 'BC' //this throw error
or queryText = 123 //this actually works
//I expect both case should hit the result.
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText)), __.has('Test', textP.containing(queryText)));
but get 'InternalFailureException\' error
Is it possible I can write a single query regardless the datatype?
if not possible, or at least make textP.containing work with multiple query assuming I know the datatype? right now the containing search throw error if the property contains number
It looks like you have the closing bracket in the wrong place inside the or() step. You need to close the first has step before the comma.
In your example
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText), __.has('Test', textP.containing(queryText))));
Which should be
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText)), __.has('Test', textP.containing(queryText)));
EDITED and UPDATED
With the corrected query and additional clarification about the data model containing different types for the same property key, I was able to reproduce what you are seeing. However, the same behavior can be seen using TinkerGraph as well as Neptune. The error message generated is is a little different but the meaning is the same. Given the fact that TinkerGraph behaves the same way I am of the opinion that Neptune is behaving consistently with the "reference" implementation. That said, this raises a question as to whether the TextP predicates should be smarter and check the type of the property before attempting the test.
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('test').property('x',12.5)
==>v[0]
gremlin> g.addV('test').property('x','ABCDEF')
==>v[2]
gremlin> g.V().hasLabel('test').or(has('x',12.3),has('x',TextP.containing('CDE')))
java.math.BigDecimal cannot be cast to java.lang.String
Type ':help' or ':h' for help.
Display stack trace? [yN]
ADDITIONAL UPDATE
I created a Jira issue so the Apache TinkerPop community can consider making a change to the TextP predicates.
https://issues.apache.org/jira/browse/TINKERPOP-2375
I have two types of entities: Subjects and Correspondents. They're both related to each other via a to-many relationship. I want to have a single fetchRequest that I can pass to a NSFetchedResultsController which will have it return:
All of the subjects which have more than one correspondent.
All of the correspondents which have subjects that only they are apart of.
After trying a variety of things, I decided that it's not possible to make a single fetch that returns both Subjects and Correspondents, so I turned to StackOverflow and found someone else suggesting that you have a single entity which does nothing more than have relationships with the two entities you'd like to return.
So I created a third type of entity, which I called Folders, which each have an optional to-one relationship with a Subject and a Correspondent. It also has two attributes, hasCorrespondent and hasSubject, which are booleans keeping track of whether Subject or Correspondent are set.
So I wrote this predicate which returns the Folder entities:
(hasCorrespondent == 1 AND ANY correspondent.subjects.correspondents.#count == 1)
OR
(hasSubject == 1 AND subject.correspondents.#count >= 1)
The issue with this is I'm getting an error:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'Unsupported function expression count:(correspondent.subjects.correspondents)
So, any suggestions as to what I'm doing incorrectly? How can I accomplish what I'd like? Are there any additional details I should share?
UPDATE
With Martin's suggestion, I changed the offending portion to this:
SUBQUERY(correspondent.subjects, $s, $s.correspondents.#count == 1).#count > 0
But that generated a new error:
Keypath containing KVC aggregate where there shouldn't be one;
failed to handle $s.correspondents.#count
After googling around, I found suggestions to add a check that the collection being enumerated over had at least one object, but modifying the offending line to this didn't change my error messages (so as far as I can tell it did nothing):
correspondent.subjects.#count > 0 AND
SUBQUERY(correspondent.subjects, $s, $s.correspondents.#count == 1).#count > 0
I had a similar problem. I created an additional field countSubentity. And when add/remove subentity change this field. And predicate looks:
[NSPredicate predicateWithFormat:#"SUBQUERY(subcategories, $s,
$s.countSubentity > 0).#count > 0"];
This work around has been less than ideal, but it seems to get the job done:
1 - I added an attribute to subject called count.
2 - I set (part of) my expression to
ANY correspondent.subjects.count == 1
Note that no SUBQUERY() was necessary for this workaround.
3 - Everytime I modify a subject's correspondents set, I run
subject.count = #(subject.correspondents.count);
I'm still hoping for a better solution and will be happy to mark any (working) better solution as correct.