I want to find all movies which don't have styles of anthology and art.
To achieve this I am using the following query
for $movie in db:open("movies","movies.xml")/movies/movie
where not(deep-equal(($movie/styles/style),("anthology","art")))
return $movie
However, all nodes are getting selected instead of filtering them.
What is going wrong?
You query doesn't make much sense and deep-equal isn't useful here at all. The following will return all movies with a style not equal to anthology or art:
db:open("movies", "movies.xml")/movies/movie[not(styles/style = ("anthology", "art"))]
Related
I'm working on a recommendation system that recommends other users. The first results should be the most "similar" users to the "searcher" user. Users respond to questions and the amount of questions responded in the same way is the amount of similarity.
The problem is that I don't know how to write the query
So in technical words I need to sort the users by the amount of edges that has specific property values, I tried with this query, I thought it should work but it doesn't work:
let query = g.V().hasLabel('user');
let search = __;
for (const question of searcher.questions) {
search = search.outE('response')
.has('questionId', question.questionId)
.has('answerId', question.answerId)
.aggregate('x')
.cap('x')
}
query = query.order().by(search.unfold().count(), order.asc);
Throws this gremlin internal error:
org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet cannot be cast to org.apache.tinkerpop.gremlin.structure.Vertex
I also tried with multiple .by() for each question, but the result was not ordered by the amount of coincidence.
How can I write this query?
When you cap() an aggregate() it returns a BulkSet which is a Set that has counts for how many times each object exists in that Set. It behaves like a List when you iterate through it by unrolling each object the associated size of the count. So you get your error because the output of cap('x') is a BulkSet but because you are building search in a loop you are basically just calling outE('response') on that BulkSet and that's not valid syntax as has() expects a graph Element such as a Vertex as indicated by the error.
I think you would prefer something more like:
let query = g.V().hasLabel('user').
outE('response');
let search = [];
for (const question of searcher.questions) {
search.push(has('questionId', question.questionId).
has('answerId', question.answerId));
}
query = query.or(...search).
groupCount().
by(outV())
order(local).by(values, asc)
I may not have the javascript syntax exactly right (and I used spread syntax in my or() to just convey the idea quickly of what needs to happen) but basically the idea here is to filter edges that match your question criteria and then use groupCount() to count up those edges.
If you need to count users who have no connection then perhaps you could switch to project() - maybe like:
let query = g.V().hasLabel('user').
project('user','count').
by();
let search = [];
for (const question of searcher.questions) {
search.push(has('questionId', question.questionId).
has('answerId', question.answerId));
}
query = query.by(outE('response').or(...search).count()).
order().by('count', asc);
fwiw, I think you might consider a different schema for your data that might make this recommendation algorithm a bit more graph-like. A thought might be to make the question/answer a vertex (a "qa" label perhaps) and have edges go from the user vertex to the "qa" vertex. Then users directly link to the question/answers they gave. You can easily see by way of edges, a direct relationship, which users gave the same question/answer combination. That change allows the query to flow much more naturally when asking the question, "What users answered questions in the same way user 'A' did?"
g.V().has('person','name','A').
out('responds').
in('responds').
groupCount().
order(local).by(values)
With that change you can see that we can rid ourselves of all those has() filters because they are implicitly implied by the "responds" edges which encode them into the graph data itself.
graph image
enter code here
(Query to find owner)
.inE().hasLabel('OwnedBy').outV().not(inE().hasLabel('AssignedTo').has('Status', 'InUse'))
.not(
inE()
.hasLabel('AssignedTo')
.has('Status', 'InUse')
).as('cards')
.inE()
.hasLabel('AssignedTo')
.has('Status', 'FutureUse')
.as('OwnedByRequestEdges')
.outV()
.as('OwnedByRequests')
.Select('card', 'OwnedByRequests', 'OwnedByRequestEdges', 'Owner')
I really want it to give me a list of the cards and the list of the requests.
I user can have multiple cards and cards can have multiple future reservations.
In order to store all the values during traversal, you should use "store" and not "as".
Since you want the "select" to run once, you need to add fold() before it.
There was a redundant "not" filter (same filter).
(Query to find owner)
.inE().hasLabel('OwnedBy').outV()
.not(inE().hasLabel('AssignedTo').has('Status','InUse'))
.store('Cards')
.inE().hasLabel('AssignedTo').has('Status', 'FutureUse').outV()
.store('OwnedByRequests')
.fold()
.select('Cards', 'OwnedByRequests')
I want to get a list of all writers from freebase. I've done an app for musicians and it works nice http://brainbol.com/musicos where I have the next query:
var query = {
'filter':'(all type:/music/artist)',
'key' : 'blablabla...',
'lang':'es'
};
But I can't figure out how to do the same with book writers. Can u help me, thanks!
As the comments suggest /book/author is the literary equivalent type of /music/artist. The slight twist is that authors write /book/written_work instances, not /book/book instances. If you wanted to constrain your query to authors who had only written books, as opposed to poems or short stories, you'd need to add some additional constraints to your query.
(I know the OP figured this out on their own, but I want this question to stop showing up as unanswered)
I'm trying to find a way to let users select nodes from views results, and then get information from the selected nodes (such as node ID) for use in my module. This would probably be done in a form.
More broadly, what I'm trying to accomplish is to present users with a list of nodes tagged with a certain term x, have them to select any number of nodes from that list, and then have my module apply another term y to the selected nodes. I can handle that last part, but I'm struggling with creating a list of nodes that users can select from, and then somehow getting the information about the nodes selected that way.
I assumed views are the way to go but after a lot of searching I haven't found a way to achieve this functionality. Can anyone can show me a solution or point me in the right direction?
Thanks!
I'm using Drupal 7, and Views 7.x-3.7
EDIT: If I had the ability to select nodes with checkboxes via a module like VBO, I would like to do something like the following (terrible) pseudo-code:
foreach (vbo_selected_node) {
$node = vbo_selected_node -> node;
$nid = $node -> nid;
$node = node_load($nid);
$node->field_vocabulary_field['und'][0]['tid'] = $termID;
}
I hope that makes sense. Basically I want to take each selected node and apply another term to it.
I've been through a similar scenario and came up with a solution through custom module. I'm not sure if it is the best option but still you can use node_load_multiple() method. A quick reference can be found in
http://eureka.ykyuen.info/2012/08/08/drupal-7-get-mulitple-nodes-using-entityfieldquery-and-node_load_multiple/
I'm constructing an apachesolr query in my Drupal module programmatically and have had success with some aspects, but am still struggling with others.
So far, I have been able to construct a query that can search for specific text and limit the results based on terms to be filtered by with the following code:
$subquery_region->addFilter('tid', $term->tid);
$query->addFilterSubQuery($subquery_region, 'OR', 'AND');
What I'd like to achieve next is to be able to narrow the search further by adding a filter for finding certain text within a specific field in the node. Has anyone been able to do this.
I've been researching online and have tried lots of different ways such as adding the filter directly to the main search query
$query->addParam('fl', 'ss_my_field');
$query->addFilter("ss_my_field", "field_substring_to_search_for");
As well as breaking that out into a subquery to add to the main search query
$subquery_test = apachesolr_drupal_query("Test");
$subquery_test->addParam('fl', 'ss_my_field');
$subquery_test->addFilter("ss_my_field", "field_substring_to_search_for");
$query->addFilterSubQuery($subquery_test, 'OR', 'AND');
But none of these are working. They are returning an empty set, even though I know the substring exists in the field I'm adding as a filter and it has been indexed. I have verified through the apachesorl views module that the search index has been populated with that field and can see the substring exists.
Is there anything wrong with my syntax or the way I'm building the query?
If you know how to add filters for searching for text within certain fields, please share! It may not even be done with the addFilter function, but that's all I have been trying so far.
Thanks!
First you have to create an index for that specific field.
function hook_apachesolr_update_index(&$document, $node) {
$document->ss_your_field_name = $node->your_field_name;
}
where ss_* is the pattern.
ss_* -> String
is_* -> Integer
im_* -> Integer, Multivalued
After that you have to
1. delete the index - admin/settings/apachesolr/index
2. re-index the content
3. run the cron
4. check the filter that you created - admin/reports/apachesolr/index
Then, you can add filters
$query->addFilter("ss_your_field_name", "value");
Hope this helps you.
function hook_apachesolr_modify_query(&$query, &$params, $caller){
$subquery = apachesolr_drupal_query();
$subquery->add_filter("ss_my_field", "field_substring_to_search_for");
$query->add_subquery($subquery, "AND");
}