How to make a request for records where the value of the two fields match in mongoalchemy? - mongoalchemy

I have a model for mongoalchemy:
class ImportProductReport(mongo.Document):
target = mongo.IntField(default=0)
processed = mongo.IntField(default=0)
is_in_process_remove_offers = mongo.BoolField(default=False)
is_old_offers_removed = mongo.BoolField(default=False)
...
I need get records, where
ImportProductReport.is_in_process_remove_offers == False,
ImportProductReport.is_old_offers_removed == False,
ImportProductReport.target == ImportProductReport.processed.
Without last equal, all work good:
res = ImportProductReport.query\
.filter(
ImportProductReport.is_old_offers_removed == False,
ImportProductReport.is_in_process_remove_offers == False
)\
.all()
But if I try to write something like this:
res = ImportProductReport.query\
.filter(
ImportProductReport.is_old_offers_removed == False,
ImportProductReport.is_in_process_remove_offers == False,
ImportProductReport.target == ImportProductReport.processed
)\
.all()
I have an error:
AttributeError: 'bool' object has no attribute 'obj'
Tell me, please, how to add this last condition in my query? :)

If it someone help, I found the answer to my question.
Mongoalchemy allows queries with a syntax, similar to the syntax of the original MongoDB.
Therefore, query, that I need, can be written as follows:
res = ImportProductReport.query\
.filter({
'is_old_offers_removed': False,
'is_in_process_remove_offers': False,
'$where': 'this.target == this.processed'
})\
.all()

Related

Boolean statement for multiple filtering Swift

I'm currently creating an app in Swift 4.2 which I'd like a filtering feature in place which allows the user to select multiple filters.
I have an array of the currently selected filters, for example ["Low", "Unread"]. I also have an array of the objects being filtered. But I'm struggling to figure out how to apply multiple filters to this array, especially due to the objects have children which in turn have properties which are filtered against. For example object array holds bulletin.importance.name which is the property that "Low" would be checked against.
The following code is a boolean returning function which will get the filters to be used on the array of bulletin objects:
return (bulletin.bulletinVersion?.issued == true) && (scopes.contains("All") || (scopes.contains((bulletin.bulletinVersion?.bulletin?.importance?.name)!) ||
(!scopes.contains(where: {$0 == "Low" || $0 == "Normal" || $0 == "High"}))) && (scopes.contains(bulletin.read(i: bulletin.firstReadDate)) ||
(!scopes.contains(where: {$0 == "Unread"}))) &&
(scopes.contains(bulletin.signed(i: bulletin.signDate)) && bulletin.bulletinVersion?.bulletin?.requiresSignature == true) && scopes.contains(bulletin.favourited(i: bulletin.favourite)))
This is my current attempt of the boolean check. I wish for it to be hard set so if the user selects "High" and "Unread" it will only show objects which match both of those filters.
The function is called here, getting the filters and filtering an array of ALL bulletins into which ones should be shown based upon the filters:
currentBulletinArray = bulletinArray.filter({bulletin -> Bool in
let doesCategoryMatch = getScopeFilters(issued: true, scopes: scope, bulletin: bulletin, signature: true)
if searchBarIsEmpty(){
return doesCategoryMatch
} else {
return doesCategoryMatch && (bulletin.bulletinVersion?.bulletin?.name?.lowercased().contains(searchText.lowercased()))!
}
})
I want to be able to set any combination of filters, where the returning .filter predicate will show only the bulletins which match ALL the filters.
So, Unread + Unsigned + High will show all High Importance bulletins where they are unread and unsigned.
Instead of trying to shove a huge amount of boolean combinations into one statement, I decided to place each filter into a dictionary:
public var filters:[String: Any] = ["importance":[],
"unread": false,
"unsigned": false,
"favourite": false]
The importance filter will hold an array of strings, for example ["Low", "Medium", "High"].
When the filter buttons are clicked the filters will be toggled if they are a bool or appended/removed from the array:
if(!importanceToAdd.isEmpty){
filters["importance"] = importanceToAdd
}
if(cell.filterTitleLabel.text == "Unread")
{
filters["unread"] = true
}
if(cell.filterTitleLabel.text == "Unsigned")
{
filters["unsigned"] = true
}
if(cell.filterTitleLabel.text == "Favourites")
{
filters["favourite"] = true
}
Then, in a seperate function, I check to see if the filters are set, independently of one another. If so, filter the array fo bulletins by each of these conditions:
if let importance = filters["importance"] as! [String]?{
if(importance.count != 0){
filteredBulletins = filteredBulletins.filter({importance.contains(($0.bulletinVersion?.bulletin?.importance?.name)!)})
}
}
if let unread = filters["unread"] as! Bool?
{
if(unread)
{
filteredBulletins = filteredBulletins.filter({$0.firstReadDate == nil})
}
}
if let unsigned = filters["unsigned"] as! Bool?
{
if(unsigned)
{
filteredBulletins = filteredBulletins.filter({$0.bulletinVersion?.bulletin?.requiresSignature == true && $0.signDate == nil})
}
}
if let favourite = filters["favourite"] as! Bool?
{
if(favourite)
{
filteredBulletins = filteredBulletins.filter({$0.favourite == true})
}
}
The inclusion and removal of filters to a dictionary really made my needs more clear. Trying to create a monster of a boolean statement would have been infinitely difficult to be dynamic enough to match each possible combination of filters (I'm not even sure it would have been possible).
But thank you to all who commented to offer alternative solutions, you really helped me think outside of the box! :)
I am not sure what you are asking, but here goes. First you could format your code to be more readable.... I know multiple return points were considered bad, but the tide seems to be turning a little on that. I would pick out the cases in order of importance and return any definite booleans you can find. For example (untested code as I do not know what Bulletin and Scopes are):
func foo(bulletin: Bulletin, scopes: Scopes) -> Bool {
if bulletin.bulletinVersion?.issued == true && scopes.contains("All") {
return true
}
if scopes.contains(bulletin.bulletinVersion?.bulletin?.importance?.name)! {
return true
}
if scopes.contains(bulletin.bulletinVersion?.bulletin?.importance?.name)! {
return true
}
if !scopes.contains(where: {$0 == "Low" || $0 == "Normal" || $0 == "High"})
&& (scopes.contains(bulletin.read(i: bulletin.firstReadDate) {
return true
}
if !scopes.contains(where: {$0 == "Unread"})
&& scopes.contains(bulletin.signed(i: bulletin.signDate)
&& bulletin.bulletinVersion?.bulletin?.requiresSignature == true
&& scopes.contains(bulletin.favourited(i: bulletin.favourite)) {
return true
}
return false
}
Note that each of these clauses tests for true and returns it if appropriate, so the function returns as soon as a true case is found. The order of the tsts might have an effect on the logic.
I would consider creating a protocol with a method that took a bulletin, scope and returned true or false.
protocol Filter {
func test(bulletin: Bulletin, scopes: Scopes) -> Bool
}
Then creating implementors of this protocol:
class AFilter: Filter {
func test(bulletin: Bulletin, scopes: Scopes) -> Bool {
if bulletin.bulletinVersion?.issued == true && scopes.contains("All") {
return true
}
return false
}
}
Once you have built a list of filter instances you could do (modified to match clarified requirements):
for filter in filters {
if !filter.test(bulletin: bulletin, scopes: scopes) {
return false
}
}
return true
(Bonus: note how easy it was to change the logic with this design pattern)

Logic error in null clause

hi I have the following function :
def signup(String name){
def x =Human.where{name == name}
if(x != null)
{
def myhuman=new Human(name: name)
if(myhuman.save() && myhuman.validate())
{
redirect(url:"https//localhost:8080")
}
}
else
{
return
}
}
It works fine. I can create people with different names and I can't create a person with the same name, however I was wondering in that if why do we check for x!=null, shouldn't we check for x == null because we first look if such a person exists and if does not we create it. I tried with x==null and I can't ever create Human, can someone explain?
You check for x != null because you can not perform operations on a null object now can you? In fact it's more Groovy to do the following:
if (!x) {
// Logic
}
This works because of the Groovy Truth.
If x == null validates to true, then you proceed as normal performing whatever operations you need. However, since in your case x is not null, x == null will validate to false and skip the if block. This isn't specific to Grails, it's general programming.
You can use an Elvis operator, if the user does not exist you create a new one.
When a Human exist, it has an id, so you check if has an id, if not, you save it and do the redirect.
You don't need to validate the object, the save method validates the object before saving it, and if it is not validated, returns false.
Human human = Human.findByName(name)?: new Human(name: name)
if(!human.id && human.save()){
redirect(url:"https//localhost:8080")
}else{
return
}

How to parameterize a boolean expression in Linq?

I have a Linq statement that looks something like:
Report.Where(a=>a.Property == 1 || a.Property == 2 || a.Property == 3).Count()
I would like to know if I can refactor the statement into something of the form:
Report.Where(a=a.Property == validProperties)
where I can store a set of validProperties as an array of integers.
You can use Contains method
var idsToCheck = new List<int> {1,2,3};
var someCount = Report.Where(a=>idsToCheck.Contains(a.Property)).Count();
Or call the Count first and pass the lambda expression to that.
var someCount = Report.Count(a => idsToCheck.Contains(a.Property));

How to make where condition include nil value

I find ActiveRecord, funnel value is not "input" value
and I make where condition
here is my code
#calls = Call.searchable.where.not(funnel: "input")
these command work good, but result is also except nil value
I wanna only funnel is not 'input'
how to add OR condition in where statement
SQL Statement is
select * from call where is_visible = 1 and (funnel != 'input or funnel is null)
The blow code should help you.
#calls = Call.searchable.where("funnel != 'input' or funnel is null")
This will also work if values are dynamic
Call.searchable.where("funnel != ? OR funnel is ?”,#value1, nil)

how can I use FirstOrDefault()?

I have this code and I want to set a value to Viewdate when the expression returns no data:
ViewData["Fix"] = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault().NumCoefficientFix;
can I set zero or a "Text" for that? I no, what can I do?!
note: FirstOrDefault(null) cause an error.
If I understand your question correctly, the following code should solve your problem:
var p = db.PreStatusViws.Where(c => c.LkpNameFix == "1").FirstOrDefault();
if(p != null)
ViewData["Fix"] = p.NumCoefficientFix;
else
ViewData["Fix"] = 0;
Default will return the default for the data type. If the data type in that place is a reference type (e.g. string) the default value will always be null, and therefore the following .NumsCoefficientFix member will throw a NullReferenceException.
The default value is built into .NET and not changeable, and is always given if the result set contains no value.
#Mikey has already given the code sample in his answer that I would suggest.
If you first select the numeric column, FirstOrDefault will work as you intend, returning either a value or 0 (the default for numeric types):
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1");
If NumCoefficientFix is a nullable type, then use the ?? operator to convert the null into 0:
ViewData["Fix"] = db.PreStatus
.Select (c => c.NumCoefficientFix)
.FirstOrDefault (c => c.LkpNameFox == "1") ?? 0;
Selecting the NumCoefficientFix first is also (slightly) more efficient for LINQ-to-database queries, in that the SQL generated will select only that column.
You just have to select your NumCoefficientFix property before calling FirstOrDefault:
ViewData["Fix"] = db.PreStatusViws
.Where(c => c.LkpNameFix == "1")
.Select(c => c.NumCoefficientFix)
.FirstOrDefault();`
Or in LINQ notation:
ViewData["Fix"] = (from c in db.PreStatusViws
where c.LkpNameFix == "1"
select c.NumCoefficientFix
).FirstOrDefault();

Resources