Neo4jclient C#: WHERE x IN List - cypher

The question is simple. Is it possible to make a WHERE x IN List in Neo4jClient?
Here is an Cypher example:
MATCH (tobias { name: 'Tobias' }),(others)
WHERE others.name IN ['Andres', 'Peter'] AND (tobias)<--(others)
RETURN others
Thank you

Neo4jclient simply wraps the Cypher REST interface, so yes. Just replace the Cypher keywords with their equivalent methods in IGraphClient and pass whatever you want to .Where (). (I also rewrote your query a little but you can ignore that)
var others = graphClient.Cypher
.Match("({ name: 'Tobias' })<--(others)")
.Where("others.name IN ['Peter', 'Andres']")
.Return(others => ...).Results;
Replace the three dots with what you want to deserialize to, for example others.As<IEnumerable<User>>().

Related

undefined method `and' for #<Arel::Attributes::Attribute

I'm having an issue getting a query to work.
I'm essentially trying to write something like the following SQL, with the literal 5 replaced with a variable:
SELECT *
FROM "my_table"
WHERE 5 BETWEEN "my_table"."minimum" AND "my_table"."maximum"
This is what I have at the moment:
MyModel.where(
Arel::Nodes::Between.new(
my_variable, (MyModel.arel_table[:minimum]).and(MyModel.arel_table[:maximum])
)
)
Please ignore the way I am using arel_table, the actual query has multiple joins and is more complex, but this is the most minimum reproducible example I have to demonstrate the problem.
The error, as in the subject of the question is as follows:
undefined method `and' for #<Arel::Attributes::Attribute:0x00007f55e15514f8>
and method is for Arel::Nodes::Node i.e. MyModel.arel_attribute[:name].eq(Arel::Nodes::Quoted.new('engineersmnky')) This is an Arel::Nodes::Equality and you can chain with and.
That being said you can construct an Arel::Nodes::And for yourself via
Arel::Nodes::And.new([left,right])
Then we can pass this to the Between class like so
Arel::Nodes::Between.new(
Arel::Nodes::Quoted.new(my_variable),
Arel::Nodes::And.new([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
)
The Arel::Nodes::Quoted (also: Arel::Nodes.build_quoted(arg)) is not needed in your case since your my_variable is an Integer which can be visited and will be treated as an Arel::Nodes::SqlLiteral but I find it best to let arel decide how to handle the quoting in case your my_variable ends up being some other un-visitable Object
There are other ways to create a Between and other ways to create an And depending on what objects you are dealing with.
between is a Arel::Predication and these predications are available to Arel::Nodes::Attribute objects e.g.
MyModel.arel_table[:minimum].between([1,6])
and as mentioned is available to Arel::Nodes::Node and instances of this class provides a convenience method (create_and) for creating an And so we could do the following:
Arel::Nodes::Node.new.create_and([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
There are a number of other ways to hack this functionality together by using other Arel classes but this should get you headed in the right direction.

[] or () in REST Urls

Has anyone used either [] or () in your REST API urls?
hypothetical examples:
/cars?[colors]:red,[engineType]:13
/cars?(colors):red,(engineType):13
says give me all cars with color red and a certain engine type. Colors is a sub property of the car resource.
Has anyone seen any issues using these to be aware of or is it pretty common to use?
Here's another example. Give me all the cities but only the cities where its people drink coffee
/cities?filter=(people[drinks[type]:6])
or I could even allow more sets as to perform ANDs like this
/cities?filter=(people[drinks[type]:6]),(another layer of filtering)&paging=(offset:10, limit:2)
essentially in the second, the comma itself is an implicit AND for the query because () denotes a filtering criteria so we have one filtering criteria, comma, second filtering criteria so this could easily be wired up to SQL via () and () if you think about it when parsing the url values out of the request and passing it down to a query in the backend.
this is an idea I have.
() - denotes one filter level, adding multiple () are multiple filters
[] - denotes a sub property of a resource
so the above allows the caller to say give me a list of cities but only those whos people like to drink coffee (type 6).
There isn't really an official specification of REST, but this is very unusual. The normal way to do this is to urlencode your parameters in key=value form. Almost all libraries are going to help you do that. You'd have to hand-parse this custom format you've invented (and you need to figure out any escaping issues; what if , or [ can be part of the string? It's unclear what the brackets are getting you in any case.
A more usual way to approach this would be:
/cars?color=red&engineType=13
There are 2 frequent patterns I met so far:
/cars/?colors=red&engineType=13
/cars/colors:red/engineType:13/
Using [] or () in URIs is not common. I don't think you'll have any issues by using them if that's what you desire. Just don't use {} if you want to use URI templates too.

What is the Dump extension used for, and why is it so popular?

To me, adding "Dump" to the end of an expression doesn't seem to do anything different, at least for seeing rows in a table. Can you point me to an example of where it is handy?
If you are just working with an expression, there is no reason to call Dump—it's called automatically. But, in the language selection box, LINQPad allows allows the selection of Statements and Program. Once you select one of those, you don't get any Dump output unless you call it.
With Statements or Programs, you might want to call Dump on multiple times. In those cases, it is handy to pass the Description parameters so you can distinguish the output.
There are also other parameters you can use to shape the output, such as depth, which limits the substructure details.
Simple example (Language=C# Statements):
var integers = Enumerable.Range(1,10);
integers.Select(i => new { i, v = i * i}).Dump("Squares");
integers.Select(i => new { i, v = i * i * i}).Dump("Cubes");
var output = "λ is awesome";
Encoding.UTF8.GetBytes(output)
.Dump("UTF-8");
Encoding.GetEncoding("Windows-1252").GetBytes(output)
.Dump("Windows-1252 (lossy)");

Passing a block to .try()

This question is about using the .try() method in rails 3 (& a bit about best practice in testing for nil also)
If I have a db object that may or may not be nil, and it has a field which is eg a delimited string, separated by commas and an optional semi-colon, and I want to see if this string contains a particular sub-string, then I might do this:
user_page = UserPage.find(id)
if user_page != nil
result = user_page.pagelist.gsub('\;', ',').split(",").include?(sub)
end
So, eg user_page.pagelist == "item_a,item_b;item_c"
I want to re-write this using .try, but cannot find a way of applying the stuff after pagelist
So I have tried passing a block (from this link http://apidock.com/rails/Object/try)
user_page.try(:pagelist) {|t| t.gsub('\;', ',').split(",").include?(sub)}
However, the block is simply ignored and the returned result is simply pagelist
I have tried other combinations of trying to apply the gsub etc part, but to no avail
How can I apply other methods to the method being 'tried'?
(I dont even know how to phrase the question in an intelligible way!)
I think you're probably coming at this wrong - the quick solution should be to add a method to your model:
def formatted_pagelist
(pagelist || "").split(/[;,]/)
end
Then you can use it where ever:
user_page.formatted_pagelist.include? sub
Strictly speaking, I'd say this goes into a decorator. If you're not using a decorator pattern in your app (look into draper!), then a model method should work fine.

How to make Lucene match all words in query?

I am using Lucene to allow a user to search for words in a large number of documents. Lucene seems to default to returning all documents containing any of the words entered.
Is it possible to change this behaviour? I know that '+' can be use to force a term to be included but I would like to make that the default action.
Ideally I would like functionality similar to Google's: '-' to exclude words and "abc xyz" to group words.
Just to clarify
I also thought of inserting '+' into all spaces in the query. I just wanted to avoid detecting grouped terms (brackets, quotes etc) and potentially breaking the query. Is there another approach?
This looks similar to the Lucene Sentence Search question. If you're interested, this is how I answered that question:
String defaultField = ...;
Analyzer analyzer = ...;
QueryParser queryParser = new QueryParser(defaultField, analyzer);
queryParser.setDefaultOperator(QueryParser.Operator.AND);
Query query = queryParser.parse("Searching is fun");
Like Adam said, there's no need to do anything to the query string. QueryParser's setDefaultOperator does exactly what you're asking for.
Why not just preparse the user search input and adjust it to fit your criteria using the Lucene query syntax before passing it on to Lucene. Alternatively, you could just create some help documentation on how to use the standard syntax to create a specific query and let the user decide how the query should be performed.
Lucene has a extensive query language as described here that describes everything you want except for + being the default but that's something you can simple handle by replacing spaces with +. So the only thing you need to do is define the format you want people to enter their search queries in (I would strongly advise to adhere to the default Lucene syntax) and then you can write the transformations from your own syntax to the Lucene syntax.
The behavior is hard-coded in method addClause(List, int, int, Query) of class org.apache.lucene.queryParser.QueryParser, so the only way to change the behavior (other than the workarounds above) is to change that method. The end of the method looks like this:
if (required && !prohibited)
clauses.addElement(new BooleanClause(q, BooleanClause.Occur.MUST));
else if (!required && !prohibited)
clauses.addElement(new BooleanClause(q, BooleanClause.Occur.SHOULD));
else if (!required && prohibited)
clauses.addElement(new BooleanClause(q, BooleanClause.Occur.MUST_NOT));
else
throw new RuntimeException("Clause cannot be both required and prohibited");
Changing "SHOULD" to "MUST" should make clauses (e.g. words) required by default.