Get ISO-dates out of an neo4j node property - neo4j

Within a graph there are Person-Nodes which have properties with information about the birthday and place of birth of a person e.g.
Jaroslavice 8.10.1679
Alcudia 26.7.1689
Is it possible to get ISO-dates and the place out of that property of type text and put it in new properties ?

It is certainly possible.
One way would be to search for nodes that do not contain your new property; then use the split function to divide the text on spaces
and periods; and then reassemble the date in the format you require.
Something like this...
MATCH (person:Person)
WHERE NOT exists(person.birthdate)
WITH person,
split(person.informations,' ')[0] AS place,
split(person.informations,' ')[1] AS date
WITH person,
place,
split(date,'.')[0] AS day,
split(date,'.')[1] AS month,
split(date,'.')[2] AS year
SET person.birth_place = place,
person.birthdate = substring('0000', 0, 4 - size(year)) + year
+ '-'
+ substring('00', 0, 2 - size(month)) + month
+ '-'
+ substring('00', 0, 2 - size(day)) + day

Related

Google Ads Script (AWQL) get custom date range for reporting

I need to pull a google ads report that will get data from a fixed date (28th May) until today and push the data to a spreadsheet. I can't figure out how to define the date range for this query
I've tried googling and reading the google documentation but I can't figure it out
function main() {
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/XXX');
var sheet = spreadsheet.getSheetByName('Data')
var report = AdsApp.report(
'SELECT Date, CampaignName, AverageFrequency, Impressions, ImpressionReach ' +
'FROM CAMPAIGN_PERFORMANCE_REPORT ' +
'WHERE Impressions > 0 ' +
'DURING 20190528,TODAY');
sheet.clearContents();
report.exportToSheet(sheet);
}
I need to use today as the end date instead of the campaign end date as the end date for this query as I'm trying to pull frequency as a metric and it will just show blank values if the end date is in the future.
Please let me know if there is a way to make the query work. Thanks!
The TODAY keyword acts as the "full range" of the DURING property and cannot be used as the end part (as far as I know). The following should work.
function main() {
var endDate = new Date();
var endRange = Utilities.formatDate(endDate, 'America/Chicago', 'YYYYMMdd');
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/XXX');
var sheet = spreadsheet.getSheetByName('Data')
var report = AdsApp.report(
'SELECT Date, CampaignName, AverageFrequency, Impressions, ImpressionReach ' +
'FROM CAMPAIGN_PERFORMANCE_REPORT ' +
'WHERE Impressions > 0 ' +
'DURING 20190528,' + endRange);
sheet.clearContents();
report.exportToSheet(sheet);
}
Date ranges for the report are defined in the DURING clause of the query. Date ranges can be specified in two different ways:
A custom date range using regular AWQL syntax, for example:
SELECT Id, Criteria, AdGroupName
FROM KEYWORDS_PERFORMANCE_REPORT
DURING 20190101,20190325
A date range type, for example:
SELECT Id, Criteria, AdGroupName
FROM KEYWORDS_PERFORMANCE_REPORT
DURING LAST_7_DAYS
In your case you should use:
DURING 20190528, 20190723
There is no other option for you to do that.

Google Sheets - Add note on edit when user edits only a portion of the sheet

This may be a simple answer, I'm very new to the script editor in google sheets.
I have about 8 sheets for individual users to enter data. I would like a note showing the last modified date on a range of cells in each of the 8 sheets. Each of the 8 sheets is identical in the layout. With the code below, I'm able to get a last modified date note on column 2, row 26, and it works great. However, I can't figure out how to expand that to include columns 2-7 and rows 26-35. I assumed just entering 2:7 under range.getRow() would work, but it does not.
Any suggestions on how to achieve this? Even better, ideally having just one comment note in a single cell on the sheet(L24 as an example), that shows the last modified date of any cell edited between columns 2-8 and rows 26-35?
My goal is really just to identify the last time a user has modified any cells within that specified range.
Any suggestions would be greatly appreciated. The script is below.
/**
* The event handler triggered when editing the spreadsheet.
* #param {Event} e The onEdit event.
*/
function onEdit(e) {
// Set a comment on the edited cell to indicate when it was changed.
var range = e.range;
if(range.getRow() == 26 && range.getColumn() == 2){
range.setNote('ROW: ' + range.getRow() + " COLUMN: "+ e.range.getColumn());
range.setNote('Last modified: ' + new Date());
}}
The OP wants to create a note in cell L24 on any sheet where the edited cell is in the range B26:H35 (columns 2 to 8 inclusive).
The OP's own code could create a note in the edited cell but was only configured for edits in the range "B26". However, most of the logic was in place, and only modest changes are required.
The points to note in this answer are:
the Note is entered in cell "L24" of the edited sheet; this is made easier by defining a variable noterange.
the row and column numbers for the edited range are assigned to variables; this makes it easier to use when building the IF statement.
the edited range is assigned to a variable; this simplifies displaying the cell reference in the note.
the IF statement is in two parts: it tests whether i) the edited row is between 26 and 35 AND ii) the edited column is between 2 and 8.
the cell reference in the note is simplified by using getA1Notation.
I left the date as used by the OP, but this can be shortened/simplified
I inserted a line break between the range reference and "Date Modified" for easier reading
I created an Installable onEdit Trigger
function so54658181(e) {
// setup spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get the active sheet
var eactiveSheet = e.source.getActiveSheet();
// set the location for the Note
var noterange = eactiveSheet.getRange("L24");
// get the edited cell and find the row and column numbers
var erange = e.range;
var editedRow = erange.getRow();
var editedColumn = erange.getColumn()
// if the row is between 26 and 35, and the column is between 2 and 8, then set the note
if ((editedRow >= 26 && editedRow <= 35) && (editedColumn >= 2 && editedColumn <= 8)) {
noterange.setNote("Cell " + erange.getA1Notation() + String.fromCharCode(10) + "Last modified: " + new Date());
}
}
Formatting the Date
Add these two line anywhere above the IF statement
// set date format
var curDate = Utilities.formatDate(new Date(), "GMT+1", "E, MMM dd yyyy");
Edit the following line of the IF statement; note that it now references curDate
noterange.setNote("Latest edit: Cell " + erange.getA1Notation() + String.fromCharCode(10) + "On: " + curDate);
A link to the most recent Date and Time Patterns is included in the Google documentation.

Neo4j Aggregate Multiple Lines into a Map

I have the following Cypher script:
MATCH (sy:SchoolYear)<-[:TERM_OF*]-()<-[:DAY_OF]-(d:Day)
WHERE sy.year = 2015
OPTIONAL MATCH (d)<-[:START]-(e:Enrollment)-[:AT]->(s:School)
RETURN d.date, s.abbreviation, count(e)
ORDER BY d.date
This gives me all of the dates in the range that I want and returns number of students that have enrolled for each school for that date, or null. The only issue I have is that different schools are on different lines, causing a single date to have multiple lines. I would like to aggregate those into a single line per date.
I'm given:
1/1/2000, School 1, 5
1/1/2000, School 2, 10
1/2/2000, null, null
1/3/2000, School 1, 6
What I would like:
1/1/2000, {School 1 : 5, School 2: 10}
1/2/2000, null
1/3/2000, {School 1: 6}
I've tried:
MATCH (sy:SchoolYear)<-[TERM_OF*]-()<-[:DAY_OF]-(d:Day)
WHERE sy.year = 2015
OPTIONAL MATCH (d)<-[:START]-(e:Enrollment)-[:AT]->(s:School)
WITH d, s.abbreviation as abb, count(e) as enr
RETURN d.date, {abb:enr}
ORDER BY d.date
How should I go about this?
Here is how I would go with this aggregate each school into a map and the maps into a collection
MATCH (sy:SchoolYear)<-[TERM_OF*]-()<-[:DAY_OF]-(d:Day)
WHERE sy.year = 2015
OPTIONAL MATCH (d)<-[:START]-(e:Enrollment)-[:AT]->(s:School)
WITH d, s, count(e) as students
RETURN d.date, collect({name:s.abbreviation, students:students})
ORDER BY d.date
This is a bit ugly, but I think it returns what you are after. I tried using the school name as a key just like you did in your example and I could not get that to work either. In the end I resorted to this.
MATCH (sy:SchoolYear)<-[TERM_OF*]-()<-[:DAY_OF]-(d:Day)
WHERE sy.year = 2015
OPTIONAL MATCH (d)<-[:START]-(e:Enrolment)-[:AT]->(s:School)
// collect the schools and their counts together
with d, [s.abbreviation, count(e)] as school_count
// collect all of the school counts together by date
with d.date as date, collect(school_count) as school_counts
// format the school counts as a string with the schools
// as keys and the counts as values
with date, reduce( out = "", s in school_counts | out + s[0] + " : " + s[1] + ", " ) as school_count_str
return date, '{ ' + left(school_count_str, length(school_count_str)-2) + ' }' as school_counts
order by date

Neo4j: Conditional return/IF clause/String manipulation

This is in continuation of Neo4j: Listing node labels
I am constructing a dynamic MATCH statement to return the hierarchy structure & use the output as a Neo4j JDBC input to query the data from a java method:
MATCH p=(:Service)<-[*]-(:Anomaly)
WITH head(nodes(p)) AS Service, p, count(p) AS cnt
RETURN DISTINCT Service.company_id, Service.company_site_id,
"MATCH srvhier=(" +
reduce(labels = "", n IN nodes(p) | labels + labels(n)[0] +
"<-[:BELONGS_TO]-") + ") WHERE Service.company_id = {1} AND
Service.company_site_id = {2} AND Anomaly.name={3} RETURN " +
reduce(labels = "", n IN nodes(p) | labels + labels(n)[0] + ".name,");
The output is as follows:
MATCH srvhier=(Service<-[:BELONGS_TO]-Category<-[:BELONGS_TO]-SubService<-
[:BELONGS_TO]-Assets<-[:BELONGS_TO]-Anomaly<-[:BELONGS_TO]-) WHERE
Service.company_id = {1} and Service.company_site_id = {21} and
Anomaly.name={3} RETURN Service.name, Category.name, SubService.name,
Assets.name, Anomaly.name,
The problem I am seeing:
The "BELONGS_TO" gets appended to my last node
Line 2: Assets<-[:BELONGS_TO]-Anomaly**<-[:BELONGS_TO]-**
Are there string functions (I have looked at Substring..) that can be used to remove it? Or can I use a CASE statement with condition n=cnt to append "BELONGS_TO"?
The same problem persists with my last line:
Line 5: Assets.name,Anomaly.name**,** - the additional "," that I need to eliminate.
Thanks.
I think you need to introduce a case statement into the reduce clause something like this snippet below. If the node isn't the last element of the collection then append the "<-[:BELONGS_TO]-" relationship. If it is the last element then don't append it.
...
reduce(labels = "", n IN nodes(p) |
CASE
WHEN n <> nodes(p)[length(nodes(p))-1] THEN
labels + labels(n)[0] + "<-[:BELONGS_TO]-"
ELSE
labels + labels(n)[0]
END
...
Cypher has a substring function that works basically like you'd expect. An example: here's how you'd return everything but the last three characters of a string:
return substring("hello", 0, length("hello")-3);
(That returns "he")
So you could use substring to trim the last separator off of your query that you don't want.
But I don't understand why you're building your query in such a complex way; you're using cypher to write cypher (which is OK) but (and I don't understand your data model 100%) it seems to me like there's probably an easier way to write this query.

Setting Multiple Variables to Result of Query

I have the query below, that will return the city and state that is the shortest distance between an inputted set of points and all rows of the table Metros:
#lat = row[latitude]
#long = row[longitude]
Metros.select(
"major_city
, major_state
,(latitude - " + #lat + ")**2 + (longitude - " + #long + ")**2 as 'distance'")
.group("major_city,major_state").limit(1).order('distance ASC')
What I need to do now is set the result to two variables row[major_city] and row[major_state] with major_city set to row[major_city] and major_state to row[major_state].
How can I accomplish this task two allow for setting to the two variables independently?
It comes out with a ActiveRecord::Relation type even if it was just one piece of result, so use .first and then take it as a single record may work.

Resources