node.js - MongoDB/Mongoose aggregation or $or not working as expected? -


have checkbox buttons in html filter results via api on.click, on ajax. there 3 kinds of results: upvoted, novote, downvoted. subject of checkboxes checked, combination of upvoted, novote, , downvoted docs appear user.

the ajax calls url of api, , data reaches database call correctly after running through following loop in node.js api, loops through array of strings ["upvoted", "novote", "downvoted"] (or combination thereof) , assigns boolean value of true respective variable:

var upvoted = false; var novote = false; var downvoted = false; storyfiltering.foreach(storyfiltering); function storyfiltering(element, index, array) {     if (element == 'upvoted') {upvoted = true}     else if (element == 'novote') {novote = true}     else if (element == 'downvoted') {downvoted = true} } console.log('upvoted: ' + upvoted + ', novote: ' + novote + ', downvoted: ' + downvoted); 

these variables match booleans of voting in each of documents.

here's database structure (with voting 1 boolean ever true @ once, rest false):

to: ["user1"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 4  to: ["user2"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 2  to: ["user1", "user2"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 1  to: ["user1", "user2"], voting: {   upvoted: false,   novote: true,   downvoted: false }, rank: 5  to: ["user1"], voting: {   upvoted: false,   novote: false,   downvoted: true }, rank: 3 

the result of find (or aggregate) callback of data filtered match toggled voting booleans..and sorting them descending 'rank'.

toggling of upvoted , novote documents user1 return:

to: ["user1", "user2"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 1  to: ["user1"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 4  to: ["user1", "user2"], voting: {   upvoted: false,   novote: true,   downvoted: false }, rank: 5 

..whereas toggling upvote documents user1 return:

to: ["user1", "user2"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 1  to: ["user1"], voting: {   upvoted: true,   novote: false,   downvoted: false }, rank: 4 

..and in same pattern, toggling of upvoted + novote + downvoted documents user 1 return of documents include user 1, sorted rank (1, 3, 4, 5)..while, constrastly, toggling of downvoted documents user 2 return 0 documents.

here basic problem approach see it. trying have interaction user interface "selects" items want appear in query results. fine, seem looking "one query rule them all" , come unstuck.

taking first example, query "upvote" , "novote" documents comes out this. stating away aggregate right now, same applies query $match pipeline:

db.collection.find({     "to": { "$in": ["user1"] },     "$or": [         { "voting.upvoted": true },         { "voting.novote": true }     ] }) 

that returns expected results $or considers "either" of conditions evaluate true in order satisfy match. explained before, queries in mongodb implicitly "and" query, there no need additional operator here.

in next example, need one of criteria true, remove $or i'll leave here explanation later.

db.collection.find({     "to": { "$in": ["user1"] },     "$or": [         { "voting.upvoted": true }     ] }) 

again matches expected result returns both "user1" present "and" "upvoted" value true.

but onto interface interaction , how handle that. let have input coming interface looks this:

{    "to": "user1",    "voting": {       "upvoted": true,       "downvoted": false,       "novote": true    } } 

that confirms basic selections in user interface made query. in order "process" desired query consider following javascript code, translate whatever language want implement in. i'm going assume structure shown in variable known request:

var query = {     "to": { "$in": [] },     "$or": [] };  ( k in request ) {     if ( k == "to" )         query.to["$in"].push( request.to );      if ( k == "voting" ) {         ( v in request[k] ) {             if ( request[k][v] ) {      // if value `true`                 var obj = {};                 obj[ k + "." + v] = true;                 query["$or"].push( obj );             }         }     } } 

running code on data resulting query object looks like:

{     "to" : {             "$in" : [                     "user1"             ]     },     "$or" : [             {                     "voting.upvoted" : true             },             {                     "voting.novote" : true             }     ] } 

which same query issued first, , changing selections in request way in second example:

{    "to": "user1",    "voting": {       "upvoted": true,       "downvoted": false,       "novote": false    } } 

the resulting query object is:

{     "to" : {             "$in" : [                     "user1"             ]     },     "$or" : [             {                     "voting.upvoted" : true             }     ] } 

all left issue query uses object it's argument:

db.collection.find( query ) 

so how interact data interface. build dynamically, rather try throw of values got in response parameters in query.


Comments

Popular posts from this blog

google api - Incomplete response from Gmail API threads.list -

Installing Android SQLite Asset Helper -

Qt Creator - Searching files with Locator including folder -