Shaine Fisher
Shaine Fisher

Reputation: 325

Update relationship property when using timestamp() as value

I have this code, which is great, but as you will see it adds a new relationship with every single view of the item.

return client.Cypher
            .Match("(p:Person)", "(s:Store)")
            .Where((Person p) => p.Email == username)
            .AndWhere((Store s) => s.Name == store)
            .Merge("(product:Product { pId: {pId} })")
            .OnCreate()
            .Set("product = {newProduct}")
            .WithParams(new
            {
                pId = newProduct.pId,
                newProduct
            })
            .CreateUnique("product-[:STOCK_FROM]->s")
            .CreateUnique("(p)-[b:BROWSED{timestamp:timestamp()}]->(s)")
            .CreateUnique("(p)-[v:VIEWED{timestamp:timestamp()}]->(product)")
            .Return<Product>("product").Results.ToList();

Now ideally I would like to add a second attribute called total, which would be an int. This attribute would be incremented with each visit and the timestamp updated as a 'lastviewed', like:

            .Create("(p)-[b:BROWSED{lastviewed:timestamp(),total:1}]->(s)")
            .Create("(p)-[v:VIEWED{lastviewed:timestamp(),total:1}]->

But I am not sure of 2 things... 1. How to query for if the relationship already exists, I think it's going to be something like this:

.Match("(p:Person)-[:BROWSED]-(product)")
            .Where((Person p) => p.Email == username)

But I get stuck with an error about needing to use .With() if I run this after the .OnCreate, and this got me in a mess, but I digress..

  1. Once queried, how to I increment the data value of the total attribute?

The problem being that I see answers in here from different versions of the client, and different versions of Neo4j, I am on 2.2.3 with the latest client (downloaded today).

Someone please help! :)

Couldn't fit this in the comments so I will update here:

return client.Cypher
            .Match("(p:Person)", "(s:Store)")
            .Where((Person p) => p.Email == username)
            .AndWhere((Store s) => s.SearchIndex == store)
            .Merge("(product:Product { ASIN: {ASIN} })")
            .OnCreate()
            .Set("product = {newProduct}")
            .WithParams(new
            {
                ASIN = newProduct.ASIN,
                newProduct
            })
            .CreateUnique("product-[:STOCK_FROM]->s")
            .Merge("(p)-[b:BROWSED]->(s)")
            .OnCreate()
            .Set("b.lastviewed=timestamp(), b.total=1")
            .OnMatch()
            .Set("b.lastviewed=timestamp(), b.total=b.total+1")
            .Return<Product>("product").Results.ToList();

Perfect :)

Upvotes: 0

Views: 60

Answers (1)

Michael Hunger
Michael Hunger

Reputation: 41706

I would use MERGE with ON CREATE SET and `ON MATCH SET``

MERGE (p)-[b:BROWSED]->(s)
ON CREATE SET b.total = 1
ON MATCH SET b.lastviewed=timestamp(), b.total=b.total+1

Not sure how good the MERGE support is in Neo4jClient

Or if you want to stay with CREATE

CREATE UNIQUE (p)-[b:BROWSED]->(s)
SET b.total = coalesce(b.total,1)+1, b.lastviewed=timestamp()

Upvotes: 1

Related Questions