Lucene neo4j sort with boolean fields - sorting

I have indexed some documents (nodes of neo4j) with a boolean property which not always is present.
Eg.
Node1
label : "label A"
Node2:
label : "label A" (note, same label of node1)
special : true
The goal is to get Node2 higher than node 1 for query "label A".
Here the code:
Index<Node> fulltextLucene = graphDb.index().forNodes( "my-index" );
Sort sort = new Sort(new SortField[] {SortField.FIELD_SCORE,
new SortField("special", SortField.????, true) });
IndexHits<Node> results = fulltextLucene.query( "label", new QueryContext( "label A").sort(sort));
How can I accomplish that?
Thanks

are you sure about indexing a property which has only 2 possible values (true, false)?
because indexing means creating a unique value by which you know the position in the database. this unique value depends on the value of the property.
when you have many properties with the same values, the index creates so called collisions - simply, it has several results for an index query. when you are traversing the graph sequentially (without an index), you also have several results which you must choose from. thus, having an index on many nodes with just 2 property values could be worthless.
i suggest create 1 node with this priority value and make relationships to it whenever you need to prioritize a node.

If you want to sort a boolean value like this, you could just use string sorting: SortField.STRING.
This will alfabetically sort the value, so false first, then true. No values (null) come for false.

Related

Laravel model query array against array

I'm looking for a way to find eloquent model based on 2 arrays. Basically, I have a model which includes a array field and is stored in a DB.
Object 1 : rankings = ['red', 'blue']
Object 2 : rankings = ['orange', 'yellow']
Object 3 : rankings = ['orange', 'purple']
The user can select some colors and then wants to find all the object that have at least one color he has slected. Thus, in my controller, I would like to find all the instances that have at least one element of a query array. The colors chosen by the user could be :
['blue','yellow','black']
In that case, I would expect to get object 1 and 2 but not 3. Is there a way to build such query ?
Model::whereIn('rankings', ['blue','yellow','black'])->get();
Would not work as rankings is not a single field but an array as well.

Neo4j performance with cycles

I have a relatively large neo4j graph with 7 millions vertices and 5 millions of relations.
When I try to find out subtree size for one node neo4j is stuck in traversing 600,000 nodes, only 130 of whom are unique.
It does it because of cycles.
Looks like it applies distinct only after it traverses the whole graph to maximum depth.
Is it possible to change this behaviour somehow?
The query is:
match (a1)-[o1*1..]->(a2) WHERE a1.id = '123' RETURN distinct a2
You can iteratively step through the subgraph a "layer" at a time while avoiding reprocessing the same node multiple times, by using the APOC procedure apoc.periodic.commit. That procedure iteratively processes a query until it returns 0.
Here is a example of this technique. It:
Uses a temporary TempNode node to keep track of a couple of important values between iterations, one of which will eventually contain the disinct ids of the nodes in the subgraph (except for the "root" node's id, since your question's query also leaves that out).
Assumes that all the nodes you care about share the same label, Foo, and that you have an index on Foo(id). This is for speeding up the MATCH operations, and is not strictly necessary.
Step 1: Create TempNode (using MERGE, to reuse existing node, if any)
WITH '123' AS rootId
MERGE (temp:TempNode)
SET temp.allIds = [rootId], temp.layerIds = [rootId];
Step 2: Perform iterations (to get all subgraph nodes)
CALL apoc.periodic.commit("
MATCH (temp:TempNode)
UNWIND temp.layerIds AS id
MATCH (n:Foo) WHERE n.id = id
OPTIONAL MATCH (n)-->(next)
WHERE NOT next.id IN temp.allIds
WITH temp, COLLECT(DISTINCT next.id) AS layerIds
SET temp.allIds = temp.allIds + layerIds, temp.layerIds = layerIds
RETURN SIZE(layerIds);
");
Step 3: Use subgraph ids
MATCH (temp:TempNode)
// ... use temp.allIds, which contains the distinct ids in the subgraph ...

Swift/Firebase sorting

I am currently experiencing some issues regarding table view sorting from firebase. What I am trying to achieve is to list 5 different price tiers in a table view, all named (tier1, tier5, tier12, tier24, tierPermanent) - each containing a value (the price).
However, while fetching these values from the database, I find it rather difficult to show these in a table view - both containing text (the time) and the price tiers. What I am doing now, is that I am using observeEventType to display all the values, and then store each value in a dictionary. After that I append it to an array of dictionaries of type [[String:String]].
What I am struggling with, is to display this in a descending order in a table view. Please take note that all of these 5 values are optional, and therefore they might not contain any value - so instead of showing a value on the very first row, and a blank cell at the second, and then a new value on the third row - I want it to display descending compared to the values. (The permanent value will always be on top if it contains a value, or else tier24 will be on top, or else tier12.). For each cell.
I know I would access the unique value with cell.nameLabel.text = cell[indexPath.row]["tier.."] as? String - but the problem is that I need to have some sort of ordering, and make sure the data isn't displayed twice. (order with both key and value - to display both key and value in the same cell.).
Any ideas on how I would approach this?
Thanks in advance.
There's really not enough data to fully address the question but how about this:
A Firebase structure:
tiers
-Y0998uas9j
tier_type: tier_24
time: 20160705130100
sort_order: 1
-Ykja9s9js9
tier_type: tier_05
time: 20160705130300
sort_order: 3
-Yukl9jh8sj
tier_type: tier_permanent
time: 20160705130500
sort_order: 0
tiers have a sort order to keep them in the correct order.
tier_permanent = 0
tier_24 = 1
tier_12 = 2
tier_05 = 3
tier_01 = 4
and some code to read them in and keep the sorted, descending:
var myArray = [[String:String]]()
let tiersRef = self.myRootRef.child("tiers")
tiersRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
for child in snapshot.children {
var dict = [String: String]()
dict["fbKey"] = child.key as String
dict["tier_type"] = child.value["tier_type"] as? String
dict["timestam"] = child.value["time"] as? String
dict["sort_order"] = child.value["sort_order"] as? String
myArray.append(dict)
}
myArray.sortInPlace( {$0["sort_order"] < $1["sort_order"]} )
self.mySuperTableView.reloadData()
for dict in myArray { //meh, print them so show they are sorted
print(dict)
}
})
This addresses: keeping them sorted, descending, and if the tires are not present in the database, they will obviously not be read in.
The issue is though, it's unclear from he question the correlation between the tier names and the value (time?). I'll update once more information has been presented.

Linq comparing DataTable with List<String>

I have a string list (List) that contains delimited fields. An example would be:
List[0] = "7/1/2013,ABC,123456"
List[1] = "7/2/2013,DEF,234567"
I also have a DataTable where a record either will or will not contain the the values from the 2nd and 3rd column in the String List:
Example
Row[0][0]="ABC" <-----String
Row[0][1]=123456 <-----Int32
What I want to do is find any records (via Linq) in the DataTable that DO NOT have corresponding values in the String List.
I've been googling for a while, and can't quite find the right way to do this with Linq...can anyone help?
This code snippet should give you an enumeration of the indices that do not have the appropriate DataTable values:
var correspondingRecords =
from index in Enumerable.Range(0, List.Count)
let items = List[index].Split(',')
where !(item[1] == Row[index][0] && item[2] == Row[index][1])
select index;
The basic idea is to iterate over the indices in order to make sure that you're comparing the appropriate rows and list items to one another. Once you do that, it's simple enough to parse the list item and make the appropriate comparisons.

Finding the lowest unused unique id in a list

Say there's a list. Each item in the list has a unique id.
List [5, 2, 4, 3, 1]
When I remove an item from this list, the unique id from the item goes with it.
List [5, 2, 3, 1]
Now say I want to add another item to the list, and give it the least lowest unique id.
What's the easiest way to get the lowest unique id when adding a new item to the list?
Here's the restriction though: I'd prefer it if I didn't reassign the unique id of another item when deleting an item.
I realise it would be easy to find the unique id if I reassigned unique id 5 to unique id 4 when I deleted 4. Then I could get the length of the list (5) and creating the new item with the unique id with that number.
So is there another way, that doesn't involve iterating through the entire list?
EDIT:
Language is java, but I suppose I'm looking for a generic algorithm.
An easy fast way is to just put your deleted ids in a priority queue, and just pick the next id from there when you insert new ones (or use size() + 1 of the first list as id when the queue is empty). This would however require another list.
You could maintain a list of available ID's.
Declare a boolean array (pseudo code):
boolean register[3];
register[0] = false;
register[1] = false;
register[2] = false;
When you add an element, loop from the bottom of the register until a false value is found. Set the false value to true, assign that index as the unique identifier.
removeObject(index)
{
register[index] = false;
}
getsetLowestIndex()
{
for(i=0; i<register.size;i++)
{
if(register[i]==false)
{
register[i] = true;
return i;
}
}
// Array is full, increment register size
register.size = register.size + 1;
register[register.size] = true;
return register.size;
}
When you remove an element, simply set the index to false.
You can optimise this for larger lists by having continuality markers so you don't need to loop the entire thing.
This would work best for your example where the indexes are in no particular order, so you skip the need to sort them first.
Its equivalent to a search, just this time you search for a missing number. If your ID's are sorted integers, you can start going from bottom to top checking if the space between two ID's is 1.
If you know how many items in the list and its sorted you can implement a binary search.
I don't think you can do this without iterating through the list.
When you say
'Now say I want to add another item to
the list, and give it the least
highest unique id. '
I assume you mean you want to assign the lowest available ID that has not been used elsewhere.
You can do this:
private int GetLowestFreeID(List list){
for (int idx = 0; idx < list.Length; ++i){
if ( list[idx] == idx ) continue;
else return idx;
}
}
this returns the lowest free index.
This assumes your list is sorted, and is in C# but you get the idea.
The data structure that would be used to do this is a Priority Binary Heap that only allow unique values.
How about keeping the list sorted. and than you can remove it from one end easily.

Resources