0

I have a set of conditions on my node app where I am trying to implement the following if block -

if(((public==true)&&(varA=="something" || varB == "something")) || (public==false)&&(varA=="something" || varB == "something")&&(varc == "something"))

so what I tried to implement was something is -

db.foo.find({"$or":[{"$and":[{e:true},{"$or":[{d:"four"},{c:"seven"}]}]},{"$and":[{e:false},{a:"one"},{"$or":[{c:"three"},{c:"seven"}]}]}]})

Now, the variables varA,varB,varC are dynamic so they depend on the user's requests. so I can't write the query object as it is. I will have to write it in an array fashion

( like obj["$or][0]["$and"][e] = true; )

or something along these lines.

can I simplify my query more here ? or is there is a better and more efficient way of getting this required collection.

Stennie
  • 63,885
  • 14
  • 149
  • 175
Harshit Laddha
  • 2,044
  • 8
  • 34
  • 64

1 Answers1

1

First, let's examine your boolean condition. It helps to write it out on multiple lines using indentation. Writing it on one line makes it nigh incomprehensible.

(public==true && (varA=="something" || varB == "something")) 
|| 
(public==false)
&& 
(varA=="something" || varB == "something") 
&& 
(varc == "something")

Let's simplify this. Let P be public==true and let A, B, C be the obvious conditions. I'm not sure if all the "something"'s are meant to be all different values or all the same or what, so I'm going to assume that for a fixed value of *, var* conditions use the same "something". Then the condition is

(P && (A || B)) 
|| 
~P
&& 
(A || B) 
&& 
C

This is a bit goofy so let's try to simplify further. The easiest way to do this is to use the symbol + for or || and * for and && since the rules for boolean algebra work like the rules for + and * in this way. Not is ~. I'll start using juxtaposition for *, too.

(P * (A + B)) + ~P * (A + B) * C =
PA + PB + (~P)AC + (~P)BC =
A(P + (~P)C) + B(P + (~P)C)

OK. Let's think about this condition. Clearly, we need one of A and B to be true. Then we need P + (~P)C to be true. It's pointless to check ~P in the condition, since if P is true we win, else we need C, so we can simplify the condition to

A(P + C) + B(P + C)

As a query object this looks like

{
    "$or" : [
        {
            varA : "something",
            "$or" : [
                { "public" : true },
                { varC : "something" }
            ]
        },
        {
            varB : "something",
            "$or" : [
                { "public" : true },
                { varC : "something" }
            ]
        },
    ]
}

I would create this object in Javascript as follows:

var myQuery = {
    "$or" : [
        {
            "$or" : [
                { "public" : true },
                { }
            ]
        },
        {
            "$or" : [
                { "public" : true },
                { }
            ]
        },
    ]
};
myQuery["$or"][0][varA] = "something";
myQuery["$or"][1][varB] = "something";
myQuery["$or"][0]["$or"][1][varC] = "something";
myQuery["$or"][1]["$or"][1][varC] = "something";

I'd appreciate if you and any other generous SO readers would check over this, as obviously there have been many opportunities for errors in the reasoning and symbolic manipulation.

wdberkeley
  • 11,531
  • 1
  • 28
  • 23