How to add a column to all connected nodes - mnesia table - erlang

I am trying to add new column to an existing mnesia table. For that, I use following code.
test()->
Transformer =
fun(X)-> % when is_record(X, user) -> %previous users
#userss{name = X#user.name,
age = X#user.age,
email = X#user.email,
year = 1990}
end,
AF = mnesia:transform_table(user, Transformer,record_info(fields, userss),userss),
mnesia:sync_transaction(AF).
Two records I have
-record(user,{name,age,email}).
-record(users,{name,age,email,year}).
I want to update all connected node's tables. But it fails.
{aborted,{badarg,{aborted,{"Bad transform function",user,
#Fun<test.2.61379004>,'otherserver#192.168.169.1',
{badfun,#Fun<test.2.61379004>}}},
[],infinity,mnesia}}
What is the problem here?

The problem is that an anonymous function can only be called on nodes where the module that defines it is loaded. I guess you loaded the module containing the test function only on one node in the cluster - you need to load it on all nodes for this to work. You can use the nl command ("network load") instead of l in the Erlang shell for that:
nl(my_module).
nl and other commands are described here.

Related

Basic Lua/ FREESWITCH array command

I am new to Lua, and this is an elementary question.
I a Lua script, I am querying the Postgress DB for two records via Freeswitch dbh.
I am able to set the first value as a local variable.
I am stuck at how to set the second value as a variable.
local dbh = Database.new('system');
local settings = Settings.new(dbh, A, B);
local sql = "SELECT A, B FROM TABLE WHERE A = '" .. A.."'";
local A = dbh:first_value(sql); --this gets saved correctly
local B = WHAT DO PUT HERE? ; -- Perhaps, I need to create an array instead?
dbh:release()
If you only want a specific row you should do this in the SQL command.
Alternatively you can query the entire table and run through the rows of the result.
I don't know freeswitch but that's what I found here:
https://freeswitch.org/confluence/display/FREESWITCH/Lua+API+Reference
dbh:query("query", function()) takes the query as a string and an optional Lua callback function that is called on each row returned by
the db. The callback function is passed a table representation of the
current row for each iteration of the loop.
Syntax of each row is: { ["column_name_1"] = "value_1", ["column_name_2"] = "value_2" }.
If you (optionally) return a number other than 0 from the
callback-function, you'll break the loop.
In order to use this you should learn how to define functions and how to use function values. Then it should be obvious what to do.
Maybe there is also a function that returns the query result as a table. At least that is the case for many other database interfaces. Ideally you should read the manual of the freeswitch Lua API first. Then you know what commands exist. Together with the Lua manual you'll know how to use them.

How to correctly use conditionals like IF or CASE in Cypher query language (Neo4J) to successfully create relationships?

I failed to create relationships in Neo4J and I would like to encourage anyone who has sucessfully done it to help me.
The desired result is to have a detailed visualisation of who is a brother to whom, who is who's mother and so on. I want to extract the data from single parent-child relationships. That means, setting a relationship like [:relatedTo {:how['daughter']}] if a node has a parent whose name corresponds to the field node.name and the gender of the node is F.
I have my CSV file that looks like this.
1;Jakub Hančin;M;1994;4;3
2;Hana Hančinová;F;1991;4;3
3;Alojz Hančin jr.;M;1968;15;14
4;Viera Hančinová;F;1968;9;
5;Miroslav Barus sr.;M;1965;9;
6;Helena Barusová;F;1942;;
7;Miroslav Barus jr.;M;1995;6;5
8;Martin Barus;M;1991;6;5
9;Hedviga Barusová;F;1945;;
10;Peter Hančin jr.;M;1991;12;13
11;Zuzka Hančinová;F;1996;12;13
12;Andrea Hančinová;F;1966;;
13;Peter Hančin sr.;M;1965;15;14
14;Alojz Hančin sr.;M;1937;;
15;Anna Hančinová;F;1945;;
This is my personal family tree and I would like to visualize it through Neo4J.
It is a file created with Excel, where I put the information into a table and create a database. Then it was converted to .csv file which is importable into Neo4J. I have sucessfully installed it and now I am at the point of writing the Cypher script to manage it. So far, I have this:
LOAD CSV WITH HEADERS FROM "file:c:/users/Skelo/Desktop/Family Database/Family Database CSV UTF.txt" AS row FIELDTERMINATOR ';'
CREATE (n:Person)
SET n = row, n.name = row.name,
n.personID = toInt(row.personID) , n.G = row.G,
n.Year = toInt(row.Year), n.Parent1 = row.Parent1, n.Parent2 = row.Parent2
WITH n
MATCH(n:Person),(b:Person)
WHERE n.Parent1 = b.name OR n.Parent2 = b.name
CASE b.gender
WHEN b.gender = 'F' THEN
CREATE (b)-[:isRelatedTo{how:['mother']}]->(n)
WHEN b.gender = 'M' THEN
CREATE (b)-[:isRelatedTo{how:['father']}]->(n)
RETURN *
The error message shown looks like this.
Invalid input 'A': expected 'r/R' (line 11, column 2 (offset: 389))
"CASE b.gender"
^
Somehow, I can't figure out why this does not work. Why can't I use the Case command? The Neo4J does not allow me to use anything but the command CREATE (it expects a letter R after C and not an A, this means the CREATE command).
Again, I want to do this. I have a few nodes that are correctly set. For each of those nodes (they represent people), I want to look into the Parent1 and Parent2 fields and to look for a node that has the same name as one of these fields. If it matches one of these, I want to mark that node as a father or a mother to the previous node (judging by the gender of the node, which represents the person).
This way I would like to fill the graph database with many relationships, but I fail at this very basic step. Please help me. If you can, please do not only say what is wrong and why it is wrong, but present a solution that works.
Since you want to create the isRelatedTo relationship regardless of gender and only the property is dependent upon a conditional, do this:
CREATE (b)-[r:isRelatedTo]->(n)
SET r.how = CASE b.gender WHEN 'F' THEN 'mother' ELSE 'father' END

connecting the nodes with relationships in py2neo

I have the following python code to make a graph in neo4j. I am using py2neo version 2.0.3.
import json
from py2neo import neo4j, Node, Relationship, Graph
graph = neo4j.Graph("http://localhost:7474/db/data/")
with open("example.json") as f:
for line in f:
while True:
try:
file = json.loads(line)
break
except ValueError:
# Not yet a complete JSON value
line += next(f)
# Now creating the node and relationships
news, = graph.create(Node("Mainstream_News", id=unicode(file["_id"]), entry_url=unicode(file["entry_url"]),
title=unicode(file["title"]))) # Comma unpacks length-1 tuple.
authors, = graph.create(
Node("Authors", auth_name=unicode(file["auth_name"]), auth_url=unicode(file["auth_url"]),
auth_eml=unicode(file["auth_eml"])))
graph.create(Relationship(news, "hasAuthor", authors ))
I can create a graph with nodes Mainstream_News and Authors with a relation 'hasAuthor'. My problem is when I am doing this I am having one Mainstream_News node with one Authors but in reality one author nodes has more than one Mainstream_News. I would like to make auth_name property of a Author nodes as a index to connect with the Mainstream_news nodes. Any suggestions will be great.
You are creating a new Authors node each time through your loop, even if an Author node (with the same properties) already exists.
First, I think you should create uniqueness constraints on Authors(auth_name) and Mainstream_News(id), to enforce what seem to be your requirements. This only needs to be done once. A uniqueness constraint also creates an index for you automatically, which is a bonus.
graph.schema.create_uniqueness_constraint("Authors", "auth_name")
graph.schema.create_uniqueness_constraint("Mainstream_News", "id")
But you will probably have to empty out your DB first (at least of all Authors and Mainstream_News nodes and their relationships), since I presume it currently has a lot of duplicate nodes.
Then, you can use the merge_one and create_unique APIs to prevent duplicate nodes and relationships:
news = graph.merge_one("Mainstream_News", "id", unicode(file["_id"]))
news.properties["entry_url"] = unicode(file["entry_url"])
news.properties["title"] = unicode(file["title"])
authors = graph.merge_one("Authors", "auth_name", unicode(file["auth_name"]))
news.properties["auth_url"] = unicode(file["auth_url"])
news.properties["auth_eml"] = unicode(file["auth_eml"])
graph.create_unique(Relationship(news, "hasAuthor", authors))
This is what I normally do, as I find it easier to know what's happening. As far as I know there are a but when you create_unique with only a Node, and there are no need to create the nodes, when you also have to create an edge.
I don't have the database on this computer, so please bear with me, if there are some typo'es, I'll correct it in the morning, but I guess you'll rather have a fast answer.. :-)
news = graph.cypher.execute_one('MATCH (m:Mainstream_News) '
'WHERE m.id = {id} '
'RETURN p'.format(id=unicode(file["_id"])))
if not news:
news = Node("Mainstream_News")
news.properties['id] = unicode(file["_id"])
news.properties['entry_url'] = unicode(file["entry_url"])
news.properties['title'] = unicode(file["title"])
# You can make a for-loop here
authors = Node("Authors")
authors.properties['auth_name'] = unicode(file["auth_name"])
authors.properties['auth_url'] = unicode(file["auth_url"])
authors.properties['auth_eml'] = unicode(file["auth_eml"])
rel = Relationship(new, "hasAuthor", authors)
graph.create_unique(rel)
# For-loop should end here
I've included the tree first lines, to make it more generic. It returns a node-object or None.
EDIT:
#cybersam use of schema is cool, implement that to, I'll try to use it myselfe also.. :-)
You can read more about it here:
http://neo4j.com/docs/stable/query-constraints.html
http://py2neo.org/2.0/schema.html

Trying to match values from one raw file with another raw file values in Lua

First of all: I'm an inexperienced coder and just started reading PiL. I only know a thing or two but I'm fast learning and understanding. This method is really unnecessary but I sort of want to give myself a hard time in order to learn more.
Okay so for testing and for getting to know the language more, I'm trying to grab two different values from two different files and storing them in tables
local gamemap = file.Read("addons/easymap/data/maplist.txt", "GAME")
local mapname = string.Explode( ",", gamemap )
local mapid = file.Read("addons/easymap/data/mapid.txt", "GAME")
local id = string.Explode( ",", mapid )
I'm grabbing two values which in the end are mapname and id
Once I have them, I know that using
for k, v in pairs(mapname)
It will give specific values to the data taken from the file, or at least assign them.
But what I need to do with the both tables is that if there is certain map in the server, check for the value in the table unless the map name is nil and then once having the name, grab the value of that map and match it with the id of the other file.
For example, I have in the maplist.txt file gm_construct and it is the first entry [1] and its corresponding id in mapid.txt lets say it is 54321 and it is also the first entry [1].
But now I must check the server's current map with game.GetMap function, I have that solved and all, I grab the current map, match it with the mapname table and then check for its corresponding value in the id table, which would be gm_construct = 1.
For example it would be something like
local mapdl = game.GetMap()
local match = mapname[mapdl]
if( match != nil )then --supposing the match isn't nil and it is in the table
--grab its table value, lets say it is 1 and match it with the one in the id table
It is a more complex version of this http://pastebin.com/3652J8Pv
I know it is unnecessary but doing this script will give me more options to expand the script further.
TL;DR: I need to find a function that lets me match two values coming from different tables and files, but in the end they are in the same order ([1] = [1]) in both files. Or a way to fetch a full table from another file. I don't know if a table can be loaded globally and then grabbed by another file to use it in that file.
I'm sorry if I'm asking too much, but where I live, if you want to learn to program, you have to do it on your own, no schools have classes or anything similar, at least not until University, and I'm far away from even finishing High School.
Edit: this is intended to be used on Garry's mod. The string.Explode is explained here: http://wiki.garrysmod.com/page/string/Explode
It basically separates phrases by a designated character, in this case, a comma.
Okay. If I understand correctly... You have 2 Files with data.
One with Map Names
gm_construct,
gm_flatgrass,
de_dust2,
ttt_waterworld
And One with IDs, Numbers, Whataver (related to the entries at the same position in the Map Names File
1258,
8592,
1354,
2589
And now you want to find the ID of the current Map, right?
Here is your Function
local function GetCurrentMapID()
-- Get the current map
local cur_map = game.GetMap()
-- Read the Files and Split them
local mapListRaw = file.Read("addons/easymap/data/maplist.txt", "GAME")
local mapList= string.Explode(",", mapListRaw)
local mapIDsRaw = file.Read("addons/easymap/data/mapid.txt", "GAME")
local mapIDs = string.Explode(",", mapIDsRaw)
-- Iterate over the whole map list
for k, v in pairs(mapList) do
-- Until you find the current map
if (v == cur_map) then
-- then return the value from mapIDs which is located at the same key (k)
return mapIDs[k]
end
end
-- Throw a non-breaking error if the current map is not in the Maplist
ErrorNoHalt( "Current map is not registered in the Maplist!\n" )
end
Code could have errors 'cause I couldn't test it. Pls Comment with error if so.
Source: My Experience and the GMod Wiki

Neo4j Cypher: How to stop duplicate SET if multiple CREATES

I have a complex cypher query that creates multiple nodes and increments some counters on those nodes. For sake of example here is a simplified version of what I am trying to do:
START a = node(1), e = node(2)
CREATE a-[r1]->(b {})-[r2]->(c {}), e-[r3]->b-[r4]->(d{})
SET a.first=a.first+1, e.second=e.second+1
RETURN b
The issue is that because there are two CREATE commands the SET commands run twice and the values are incremented by 2 instead of 1 as intended. I have looked to see if I can merge the multiple CREATE statements and I cannot.
My initial idea is to separate out the different creates into a batch query, however I was wondering if there is another option.
Where are you executing this query? What version of neo4j are you using?
I went to console.neo4j.org and successfully ran the following and it correctly added one to both a.first and e.second:
START a = node(1), e = node(2)
CREATE a-[r:KNOWS]->b-[r2:KNOWS]->c, e-[:KNOWS]->b-[:KNOWS]->d
SET a.first=a.first+1, e.second=e.second+1
RETURN b

Resources