Return variable state before WHERE in Cypher query - cypher

Consider the following query where some items are merged into the database and where one of the properties is converted into a relationship (all in one go):
# items=[{id: 'a', experiment: 1}, {id: 'b'}]
UNWIND $items AS item MERGE (x:Item { id: item.id })
SET x = item, x.experiment = null
WITH x, item.experiment as experiment WHERE NOT experiment IS NULL
CALL {
WITH x, experiment
MERGE (x)-[:IN_EXPERIMENT]->(e:Experiment { name: experiment })
}
RETURN x.id
This returns:
╒══════╕
│"x.id"│
╞══════╡
│"a" │
└──────┘
This is due to the fact that WHERE filters the original items from UNWIND .
What would be the most efficient way to return all items from the original list?:
╒═════════╕
│"item.id"│
╞═════════╡
│"a" │
├─────────┤
│"b" │
└─────────┘
The idea is to do not query again the whole database with another MERGE/MATCH because the data is already in memory. The best I can think on is to add another UNWIND using the original list, but there might be a better way I cannot think off.
...
WITH x, item.experiment as experiment WHERE NOT experiment IS NULL
CALL {...}
UNWIND $items AS item RETURN item.id

Related

How to delete items from an array in Vue

I have a function called updateAnswer with multiple dynamic parameters.
updateAnswer(key, answer, array = false) {
if (array) {
if(this.answers.contains.find(element => element === answer)) {
//Delete item from array if already element already exists in this.answers.contains array.
} else {
Vue.set(this.answers, key, [...this.answers.contains, answer]);
}
} else {
Vue.set(this.answers, key, answer);
}
},
I'd like to know how delete an item in the array if the value already exists in the array.
You can use method called splice:
Just reference on your array and set values in the brackets the first is referenced on the position, the second is how many datas you want to splice/delete.
The function looks like this:
this.array.splice(value, value)
Lets see on an example - you have array food= [apple, banana, strawberry] than I'm using this.food.splice(1,1)..
my array looks now like this food = [apple, strawberry] - first value in my brackets are the position, the second one is the amount of "numbers" you want to delete.
Hopefully this helps you out!
I suppose each value in this.answers.contains is unique?
Anyways, if you just want to delete the item if already exists, I suggest filter(). It should look like below:
if(this.answers.contains.find(element => element === answer)) {
this.answers.contains = this.answers.contains.filter(c => c !== answer)
}
Also, the if condition if(this.answers.contains.find(element => element === answer)) could also be replaced by if(this.answers.contains.includes(answer))
Hope that could help you.

Lodash choose which duplicates to reject

I have array of objects, objects have properties say "a", "b" and "c".
Now I need to filter out objects which has unique values of "a & b".
However c plays role on which objects to keep and which ones to reject.
If I do uniqBy on properties a and b, I will be blindly rejecting other objects. It will keep the first object it encounters in the array and reject all other duplicates.
Let me know if you need more clarification on the question.
This is how I found the uniq objects based on two properties.
var uniqArray= _.uniqBy(obj, function(elem) { return [elem.a, elem.b].join(); })
lodash uniq - choose which duplicate object to keep in array of objects
Do we have better solution?
Here is an example of input and expected output
Input: var arrayOfObj = [{a:1, b:1, c:2}, {a:1,b:1,c:1}, {a:2, b:2,c:2}];
Output: arrayOfObj = [{a:1,b:1,c:1}, {a:2, b:2,c:2}]; there should not be any duplicate a1,b1 combination
According to Lodash documentation, the order of result values is determined by the order they occur in the array. Therefore you need to order the array using the 'c' property in order to get the expected result.
To do so, you can use _.sortBy. It orders a collection in asc order based on a property or an iteratee. I think your problem could be solved using a property directly though you could use a function to provide a more accurate comparator if needed.
After that, you just perform the uniqBy action and retrieve the result:
var res = _(arrayOfObj)
.orderBy('c')
.uniqBy('a', 'b')
.value();
console.log(res);
Here's the fiddle.
As I read in the comments, your 'c' property is a timestamp. If you want to order from latest to newest, you can pass an iteratee to sort by in order to reverse the natural order by 'c':
var res = _(arrayOfObj)
.orderBy(function(obj) {
return -(+obj.c);
})
.uniqBy('a', 'b')
.value();
console.log(res);
You can check it out in this update of the previous fiddle. Hope it helps.
Would help to know what the actual data is and what you want to achieve with it. Here's an idea: group your objects based on a and b, then from each grouping, select one item based on c.
var arrayOfObj = [
{a:1, b:1, c:2},
{a:1, b:1, c:1},
{a:2, b:2, c:2}
];
var result = _.chain(arrayOfObj)
.groupBy(function (obj) {
return obj.a.toString() + obj.b.toString();
})
.map(function (objects) {
//replace with code to select the right item based on c
return _.head(objects);
}).value();

How can I do this Scala SQL (Slick 1.0.1) query in a functional rather than mutable manner?

I have a Scala Slick table of School objects and I want to filter based upon 0-5 parameters contained within a filter object SchoolFilter:
case class SchoolFilter(name: Option[String],
city: Option[String],
state: Option[String],
zip: Option[String],
district: Option[String])
A None value means "don't filter on this key at all" because I have a html page with a table of School objects and an AJAX call that does a filter based upon user input. I implemented this behaviour by creating a mutable list of all schools and then running a filter on each member of SchoolFilter that is defined. But the method doesn't seem horribly efficient, sucking in all of the records from the database and then making (potentially) 5 passes over the list before returning the results.
Is there a more functional (or perhaps more efficient) way of accomplishing this goal?
def findSchoolsByFilter(f: SchoolFilter = SchoolFilter(None, None, None, None, None),
n: Int = 5)
(implicit session: Session) = Try {
var s = collection.mutable.LinkedList(Query(Schools).list().toSeq: _*)
if (f.name.isDefined)
s = s.filter(_.name.toLowerCase.startsWith(f.name.get.toLowerCase))
if (f.city.isDefined)
s = s.filter(_.city.toLowerCase.startsWith(f.city.get.toLowerCase))
if (f.state.isDefined)
s = s.filter(_.state.toLowerCase.startsWith(f.state.get.toLowerCase))
if (f.zip.isDefined)
s = s.filter(_.zip.toLowerCase.startsWith(f.zip.get.toLowerCase))
if (f.district.isDefined)
s = s.filter(_.district.toLowerCase.startsWith(f.district.get.toLowerCase))
List(s.toSeq: _*).take(n).sorted
}
Local mutability (contained within a function, no leaked) is usually not a problem. Mutability becomes hard, when you have to reason about several places in your code modifying the same thing. But you can improve readability and efficiency of your code using a functional style. We can do the filter as a completely lazy query builder. No database round-trip, just building of an appropriate query, which means also no session needed anymore for your function.
def findSchoolsByFilter(f: SchoolFilter = SchoolFilter(None, None, None, None, None),
n: Int = 5) = {
/** Case insensitive option startsWith */
def iStartsWith( a:Column[String], bOption:Option[String] ) = bOption.map( b => a.toLowerCase startsWith b.toLowerCase )
Query(Schools).filter( s =>
Seq(
iStartsWith( s.name, f.name ),
iStartsWith( s.city, f.city ),
iStartsWith( s.state, f.state ),
iStartsWith( s.zip, f.zip ),
iStartsWith( s.district, f.district )
).flatten.reduce(_ && _) // flatten removes Nones and unwrap the Somes XMAS-Style
).take(n)
}
You could even go one step further and make schools an argument to findSchoolsByFilter, so you can lazily combine this filter with other filters.

Raven query returns 0 results for collection contains

I have a basic schema
Post {
Labels: [
{ Text: "Mine" }
{ Text: "Incomplete" }
]
}
And I am querying raven, to ask for all posts with BOTH "Mine" and "Incomplete" labels.
queryable.Where(candidate => candidate.Labels.Any(label => label.Text == "Mine"))
.Where(candidate => candidate.Labels.Any(label => label.Text == "Incomplete"));
This results in a raven query (from Raven server console)
Query: (Labels,Text:Incomplete) AND (Labels,Text:Mine)
Time: 3 ms
Index: Temp/XWrlnFBeq8ENRd2SCCVqUQ==
Results: 0 returned out of 0 total.
Why is this? If I query for JUST containing "Incomplete", I get 1 result.
If I query for JUST containing "Mine", I get the same result - so WHY where I query for them both, I get 0 results?
EDIT:
Ok - so I got a little further. The 'automatically generated index' looks like this
from doc in docs.FeedAnnouncements
from docLabelsItem in ((IEnumerable<dynamic>)doc.Labels).DefaultIfEmpty()
select new { CreationDate = doc.CreationDate, Labels_Text = docLabelsItem.Text }
So, I THINK the query was basically testing the SAME label for 2 different values. Bad.
I changed it to this:
from doc in docs.FeedAnnouncements
from docLabelsItem1 in ((IEnumerable<dynamic>)doc.Labels).DefaultIfEmpty()
from docLabelsItem2 in ((IEnumerable<dynamic>)doc.Labels).DefaultIfEmpty()
select new { CreationDate = doc.CreationDate, Labels1_Text = docLabelsItem1.Text, Labels2_Text = docLabelsItem2.Text }
Now my query (in Raven Studio) Labels1_Text:Mine AND Labels2_Text:Incomplete WORKS!
But, how do I address these phantom fields (Labels1_Text and Labels2_Text) when querying from Linq?
Adam,
You got the reason right. The default index would generate 2 index entries, and your query is executing on a single index entry.
What you want is to either use intersection, or create your own index like this:
from doc in docs.FeedAnnouncements
select new { Labels_Text = doc.Labels.Select(x=>x.Text)}
And that would give you all the label's text in a single index entry, which you can execute a query on.

Querying for close matches in MongoDB and Rails 3

So, I need to write something in Rails 3 that does a query to a MongoDB (If you don't know mongo I don't need the code just some ideas) that can query the data for close matches. For instance, let us say you are searching a collection for {item : a, item2 : b, item3 : c}. And exact match would have all three, but I also want matches that omit one of the three keys. I have two theories on how I should handle this. One would be to do multiple queries to omit certain parts of the data and the other would be to write a complex or statement. I don't feel these are the best solutions though. Could anyone else suggest something to me? Even if it is from an SQL perspective, that would work for me.
I do need something that can be done fast. This is for a search that needs to return results as fast as possible.
Yet another approach would be to use MapReduce.
With it you can calculate how many fields a document matches.
Though it's not very performant approach at the moment (but one of the most flexible).
The code can be something like this:
var m = function() {
var fieldsToMatch = {item: a, item2: b, item3: c};
for(var k in fieldsToMatch) {
if(this[k] == fieldsToMatch[k]) {
emit(this.id, {count : 1}); // emit 1 for each field matched
}
}
};
var r = function(k, vals) {
var result = {count: 0};
vals.forEach(function(v) {
result.count += v.count;
});
return result;
}
db.items.mapReduce(m, r, {out: 'out_collection'});
Why dont you just use mongodb OR, in ruby (using mongoid) you can do this by
Collection.any_of({:item => a, :item2 => b, item3 => c},{:item => a, :item2 => b},{:item => a, :item3 => c},{:item2 => b, item3 => c})
which is equivalent to
db.Collection.find({$or:[{item:a,item2:b,item3:c}],[{item:a,item2:b}],[{item:a,item3:c}],[{item2:b,item3:c}]})