MichaelE
MichaelE

Reputation: 767

What's the correct syntax to check if cypher query return zero row in javascript

I am trying to determine if a username exists before creating the user. I am using the following code. I need an elegant way to determine if the zero row is returned ...username doesn't exist. for example I know the returned row value would be zero if not found. How can I get access to the row value in the code. Can someone assist...thanks...BTW I am using neo4j3.0 Nodejs with express and Passport

neo4jSession
    .run(MATCH (user {email: newUser.email}) RETURN user);
     .then (function(result) {
            if ((not found) { 
            .run(CREATE (user: {email:newUser.email, password:newUser.password} ) ASSERT email is UNIQUE RETURN user);

            neo4jSession.close();
            })  //end of if not found

          else (found)
             {
               //   email address already exist
                console.log("email address already exist");
                neo4jSession.close();
             }
           }); //end .then
         .catch(function(error) {
              console.log(error);
                });

Upvotes: 1

Views: 1120

Answers (3)

Johnathan Maravilla
Johnathan Maravilla

Reputation: 139

The Neo4j Driver for JavaScript record module can check if a value from record exists by index or field key using the has method. When evaluating or validating the existence of any field within a record (e.g. determining if a User node contains an existing email address property), using the has instead of the get method can allow for shorter Cypher statements and condensed javascript code; which (IMO) can lead to elegance you are seeking.

Using your original example, you can use a simple Cypher statement to search if a User node contains an email property by passing in a user's input. Utilizing the Neo4j Driver for JavaScript, you can return a result stream with a single record.

Cypher Statement:

MATCH ( u:User { email: $email } )
RETURN u, u.email

If an email address exists as a User node property in the Neo4j database, a stream of records with one field named "u.email" be will returned . The record represents one user found by the statement above. You can access the field value by key using the record module's has method.

Access Record by Field Key:

result.records[0].has('u.email')

The following example is one of many ways you could implement both the simple Cypher statement and has method:

async (_, { email, password }) => {
  const session = await driver.session()
  const closeSession = await session.close()
  const endSession = await driver.close()
  let query = 'MATCH (u:User{email: $email}) RETURN u, u.email'
  return session
    .run(query, { email })
    .then(async result => {
        closeSession()
        let emailExists = result.records[0].has('u.email')
        let newUser = result.records[0].get('u').properties
        if (
            (Array.isArray(result.records) && !result.records.length) ||
            (Object.keys(result).length === 0 && result.constructor === Object)
        ) {
            if (!emailExists) {
                let query =
                    'MERGE (u:User { email: $email }) ON CREATE SET u.password = $password RETURN u'
                return session
                    .run(query, { email, password })
                    .then(result => {
                        closeSession()
                        return newUser
                    })
            } else if (Array.isArray(result.records) && result.records.length) {
                const emailExists = result.records[0].has('u.email')
                if (emailExists) {
                    closeSession()
                    throw new Error(emailExists + ' already exists.')
                } else {
                    closeSession()
                    endSession()
                    throw new Error('Internal Server Error')
                }
            } else {
                closeSession()
                endSession()
                throw new Error('Internal Server Error')
            }
        } else {
            closeSession()
            endSession()
            throw new Error('Internal Server Error')
        }
    })
    .catch(function(err) {
        closeSession()
        endSession()
        if (err) throw err
    })
  }

Note: This example validates whether a record exists first by evaluating the result with conditional statements, then the e-mail property is checked. A few errors have been handled as well.

Upvotes: 1

MichaelE
MichaelE

Reputation: 767

Though the answer from @stdob is an accepted answer on further research I found out that in case the record do exist, you can't retrieve any data on that query... so:

MATCH (user {email: newUser.email}) 
RETURN user.name AS Name, count(user)=1 as user_exists

wont yield any data if user exist. The following works:

MATCH (user {email: newUser.email}) RETURN user;
 if (!result[0]) {
        //no records found
     }
else {get user properties}

Thanks to: https://github.com/mfong/node-neo4j-passport-template/blob/master/models/user.js

Upvotes: 0

stdob--
stdob--

Reputation: 29157

Query (use counter):

MATCH (user {email: newUser.email}) 
RETURN count(user)=1 as user_exists

In javascript:

if ( result.records[0].get('user_exists') !== true ) {
  // create new user
}

And, of course, add a unique constraint to the email address for the user.

Upvotes: 0

Related Questions