Person has many addresses. I'm trying to create an address for a person if the JSON response from an API is different from any of the addresses in the db.
I wrote the following, which works with literal use cases; it prevents duplicate addresses:
p = Person.find(1)
unless p.addresses.any? { |i| i.address_1.eql?(#response['addresses'][0]['street'].upcase) }
This works by taking the array, mapping the address object, and calling eql? on the address_ column (street address).
However, if the street address is suffixed with "blvd" or "ln", I want to add that address to the person. I haven't found a method that evaluates two strings for similarities. Is there some method like similar_to? that might help me?
Related
I have node of type User which has an array property called 'emails' that contains an array of emails (strings). I am trying to write a cypher query that can be used to look up nodes that match a specific email address (in other words - given an email address, I want to look up all nodes that contain that email address within their 'emails' property.
MATCH(u:User) WHERE 'abc#gmail.com' IN u.emails RETURN u;
However, the above query returns nothing. I have confirmed that I do have a node that contains the property, see below:
u
id ed2ac321-60e3-4765-95b6-b097726454bf
emails ["abc#gmail.com"]
Not sure what I'm missing here.
EDIT: I found the issue, thanks to the question posted by stdob. I was creating the array in correctly - I was using quotes like this:
CREATE (u:User {id: 'ed2ac321-60e3-4765-95b6-b097726454bf', emails: '["abc#gmail.com"]'}) RETURN u;
Output:
u
emails ["abc#gmail.com"]
id ed2ac321-60e3-4765-95b6-b097726454bf
This internally was creating a simple string property called emails, not an array. To fix this, I removed the quotes:
CREATE (u:User {id: 'ed2ac321-60e3-4765-95b6-b097726454bf', emails: ["abc#gmail.com"]}) RETURN u;
Output:
u
emails [abc#gmail.com]
id ed2ac321-60e3-4765-95b6-b097726454bf
There's a subtle difference in the way the neo4j web interface displays the output of the above two statements, but worth a lot!
Nodes returned in neo4j seem to be special, in that they output as JSON objects, and they don't appear at all if they're null.
An example:
I have a :Person object, and they can have 0 or more :Friend relationships to another :Person.
Let's say that a :Person has the following properties: ID, firstName, lastName, sensitiveThing.
sensitiveThing is a property that might be used by our system, or could be personally accessible to the user themselves, but we don't want to return it to any other user.
If I want a query to give me back data of my friends, and friends of those friends, I might use a query like this
MATCH (me:User{ID:777})-[:Friend]-(friend:User)
WITH me, friend
OPTIONAL MATCH (friend)-[:Friend]-(foaf:User)
WHERE me <> foaf
RETURN friend.ID, friend.firstName, friend.lastName, COLLECT(foaf) AS FriendOfAFriend
While this lets me nicely bundle up friends of friends as JSON objects within a JSON array, and correctly emits an empty array if a friend doesn't have any other friends besides me, I don't want to return sensitiveThing with this query.
If I try to replace COLLECT(foaf) with a custom object only including fields I care about, like this:
COLLECT({ID:(foaf.ID), firstName:(foaf.firstName), lastName:(foaf.lastName)})
then I get what I want...until I hit the case where there are no friends of friends. When I was working with nodes before, the object wouldn't even be emitted. But now, I would get something like this returned to me:
[{ID: (null), firstName: (null), lastName: (null)}]
This is obviously not what I want.
Ideally, I'm looking for a way to return a node as before, but whitelist or blacklist properties I want to emit, so I can retain the correct null handling if the node is null (from an optional match)
If I can't have that, then I'd like a way to use a custom object, but not return the object at all if all its fields are null.
Any other workarounds or tips for dealing with optional matches are more than welcome.
You can use apoc.map.removeKeys:
WITH {p1: 1, p2: 2, p3: 3, p4: 4} as node
CALL apoc.map.removeKeys( node, ['p2', 'p4'] ) YIELD value
RETURN value
I've never seen a way to whitelist or blacklist properties in the documentation.
However, you can return your custom object by chaining collect with extract:
MATCH (me:User{ID:777})-[:Friend]-(friend:User)
WITH me, friend
OPTIONAL MATCH (friend)-[:Friend]-(foaf:User)
WHERE me <> foaf
WITH friend, collect(foaf) AS FriendOfAFriend
RETURN friend.ID, friend.firstName, friend.lastName,
extract(foaf in FriendOfAFriend | {ID:(foaf.ID), firstName:(foaf.firstName), lastName:(foaf.lastName)}) AS FriendOfAFriend
collect will return an empty list if there are no friends, extract will keep it that way.
I have a PFObject subclass which stores an array of strings as one of its properties. I would like to query for all objects of this class where one or more of these strings start with a provided substring.
An example might help:
I have a Person class which stores a firstName and lastName. I would like to submit a PFQuery that searches for Person objects that match on name. Specifically, a person should be be considered a match if if any ‘component’ of either the first or last name start with the provided search term.
For example, the name "Mary Beth Smith-Jones" should be considered a match for beth and bet, but not eth.
To assist with this, I have a beforeSave trigger for the Person class that breaks down the person's first and last names into separate components (and also lowercases them). This means that my "Mary Beth Smith-Jones" record looks like this:
firstName: “Mary Beth”
lastName: “Smith-Jones”
searchTerms: [“mary”, “beth”, “smith”, “jones”]
The closest I can get is to use whereKey:EqualTo which will actually return matches when run against an array:
let query = Person.query()
query?.whereKey(“searchTerms”, equalTo: “beth”)
query?.findObjectsInBackgroundWithBlock({ (places, error) -> Void in
//Mary Beth is retuned successfully
})
However, this only matches on full string equality; query?.whereKey(“searchTerms”, equalTo: “bet”) does not return the record in question.
I suppose I could explode the names and store all possible sequential components as search terms (b,e,t,h,be,et,th,bet,etc,beth, etc) but that is far from scalable.
Any suggestions for pulling these records from Parse? I am open to changing my approach if necessary.
Have you tried whereKey:hasPrefix: for this? I am not sure if this can be used on array values.
https://parse.com/docs/ios/guide#queries-queries-on-string-values
In the Nokogiri documentation you can find the following:
node.pointer_id # internal pointer number
This returns the internal pointer number as an integer. However, it states nowhere how this can be used to look up a node?
I would have expected something like this:
p_id = node.pointer_id
element = page.with_pointer_id(p_id)
UPDATE...to give you an idea of the use case.
I am caching lots of html pages as Nokogiri object and scan them for specific nodes. Those nodes I save to a hash, together with the number of occurence:
{"node1" => 8}
Right now its saving the whole node as key, but it would be so much more convenient to have an identifier for it. After clustering those hashes I want to retrieve the nodes again -> thats were the id should come in.
You can do this using the #traverse method available through the Nokogiri::XML::Document instance.
Here is #traverse wrapped in your #with_pointer_id method as a singleton.
class Nokogiri::XML::Document
def with_pointer_id(p_id)
traverse {|node| return node if node.pointer_id == p_id}
end
end
Now you can do this:
element = page.with_pointer_id(p_id)
This will find the node with a pointer_id matching p_id, if it exists.
Domain (just simple example):
class House {
String address
String region
Long price
static searchable = { only = ['address', 'price', 'region'] }
}
I want to search by address with price selector
Search query is:
"${address} AND price: [100 TO 1000]"
But if address='500' in search result will be Houses with price 500. I need to find house for address only by House.address + House.region
If I understood, you want to use the value of ${address} to query only on the address and region attributes.
In that case, based on the "complex" query string example at http://grails.org/Searchable+Plugin+-+Searching+-+String+Queries, your query string could be:
"+(address:${address} OR region:${address}) price:[100 TO 1000]"
Matches must have a ${address} value for address or a ${address} value for region, and have a value from 100 to 1000 for price.
Note: your input variable has the same name of an entity attribute, "address", wich can cause some confusion when trying to understand query strings using them both. Though not needed, you might want to change that, for easier readable query strings.