Mongoid embedded doc search isn't searching all embedded docs - search

Using Mongoid, I have an Order class and a LineItem class. The Order class embeds_many line_items. The standard functionality is working fine. However, searching the embedded Line Items doesn't always seem to work. For example, the LineItem class has an "account_id" field. In an attempt to find all Orders that contain at least 1 Line Item with a nil account_id field, I attempt this:
Order.where('line_items.account_id' => nil)
This returns me 2 orders that do, in fact, contain Line Items with nil account_ids. Both orders contain multiple line items, and in both orders some of the line items have account_ids, so this seems to work as expected.
HOWEVER
I happened to discover that there are actually 4 orders within our system that contain line items with nil account_ids. I verified this using something like this:
Order.all.each do |o|
puts o._id if o.line_items.where(account_id: nil).count > 0
end
This prints out 4 order IDs. I've gone into each one of those 4 and verified that each one does, in fact, contain a line item with an account_id set to nil. So, why doesn't the first search work? Why is the first search only returning 2 orders instead of 4?
After doing some digging, I discovered that, in the 2 orders that are returned by the first query, the first line item in each Order has a nil account_id. In the other 2 orders that contain line items with nil account_ids but are NOT returned by the first query, the first line item in both of those 2 orders does not have a nil account_id, so I'm wondering if the first search I used is only actually searching the first of the many embedded Line Items for each order.
Is this a Mongoid bug? Or am I doing something wrong here? I have to assume I'm doing something wrong, but I can't find any indication of what that might be.

Related

PowerApps: getting most recent record having a condition

Is it possible in PowerApps to get at the latest record, from a SharePoint list, having a certain condition?
In my case I know how to get the number, using something like this:
CountIf(Applications, Status = "Pending")
But, I would also like to get the most recent one of them. Well I suppose that would imply two conditions where the second is a Date column, but is it possible to sort it and then pick the first? Grateful for any guidance...
Yes, you can use an expression that sorts the filtered data source by the date in descending order, and take the first element, like in the expression below:
First(
SortByColumns(
Filter(Applications, Status = "Pending"),
"DateColumn",
Descending))

Tag filter with OR condition

I have four items with tags
"AA","BB","CC" and "DD" respectively.
If I want to filter tags in
Get Next Item stage
such that items with
either tag "AA" or "BB"
get picked then what should be tag filter expression?
I tried
"+AA;+BB"
But it did not pick any item.
Please help.
In the documentation of that object you can find following information about using parameter "tag" when getting new items from the queue.
Optionally, a tag mask to filter by. This can consist of any number of
tag searches - each term can be separated by a semi-colon and they are
all applied to the search (ie. they are AND'ed terms not OR'ed terms).
For example, "Account: Joint; -Balance: Overdrawn; Card: *Visa*" will
include any items which match all the terms, ie. every item must have
an 'Account: Joint' tag applied, no item can have a 'Balance:
Overdrawn' tag applied, every item must have a tag applied which
starts with 'Card: ' and then contains the text 'Visa'.
The important part in that documentation, is that all the parameters are applied, and only the items that pass all the filters with be taken from queue. I think that what you're trying to achieve here is impossible to do in one "Get next item" action.
i would advise to do one of following:
Redesign the Tags in the process
Use Two step process of getting items from queue there. E.g. First try to find all AA's, and then all BB's.
I think you can try to filter by setting "-CC;-DD", so Blue Prism filter by searching for AA or BB but without CC and DD.

How do I conditionally add a new line and tabs in Excel?

I have a list of values id, name, category, description and a variable amount of keyword values; between 0 and 18 for each row. I want to create a list of those values in the form of:
(id, 'keyword')
, (id, 'keyword')
Where the list only increments if there is a keyword to go with the identifier. This is meant to be an easy manual list for a SQL INSERT statement.
I realize that I can use &CHAR(9) for inserting tabs and &CHAR(10) for inserting new lines, and thus my sequence for proper tabulation is &CHAR(10)&CHAR(9)&CHAR(9) for each new entry.
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")
&CHAR(10)&CHAR(9)&CHAR(9)&
IF(H2<>"",CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
I've tried several different combinations such as:
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")+
IF(H2<>"",CHAR(10)&CHAR(9)&CHAR(9)&CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
and
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')",CHAR(10),CHAR(9),CHAR(9)),"")+
IF(H2<>"",CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
and
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")+
IF(H2<>"",CONCATENATE(CHAR(10),CHAR(9),CHAR(9),"(",A2,", '",UPPER(H2),"')"),"")
which all give errors in calculation. Has anyone else been dying to know how to do this and had this kind of frustration? Does anyone have a solution to this?
I actually figured this out within an hour of posting, but neglected to post the solution here in case anyone else wanted to know.
You have to CONCATENATE the whole series of IF blocks and add the CHAR(10) and CHAR(9)s to the inner CONCATENATE blocks, like so:
=CONCATENATE(IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),""),
IF(H2<>"",CONCATENATE(CHAR(10),CHAR(9),CHAR(9),"(",A2,", '",UPPER(H2),"')"),""))
Thanks,
-C§

Xpages: get count of values in multi-value field in view

I have 100 documents with a multi-value field. The field holds 5 possible values (Albert,Ben,Chris,Don,Ed) let's say. The field must contain 1 value, but can contain up to 5.
I need to compute the number of docs that contain each value, so
Albert 56
Ben 22
Chris 79
etc.
This seemed easy. I constructed a view that contains the docs, the first column is the field, and I selected show multiple documents for multiple feeds.
In SSJS loop through my master list of values in the field, and for each one do a getDocumentByKey.
myArray = applicationScope.application;
var dc:NotesDocumentCollection;
for (index = 0; index < myArray.length; ++index) {
dc = view1.getAllDocumentsByKey(myArray[index]);
Print(dc.getCount())
}
This gets the first value correctly, but none after. If I just hard code a particular value, it works. But when I call the getAllDocumentsByKey a second time, it doesn't return the right value.
I think this would work fine in LS, but in SSJS I must clear or recycle or rest something, but I don't know what.
Bryan,
Two things to try in this order:
Your first line of myArray = applicationScope.application; doesn't look right. I suspect that you are not actually getting an array here. I think you are just getting the first value from your applicationScope. Add a print statement on the next line of print(myArray.length); If it is always equal to one, that is your problem. You are not using var and you should set the variable to some java type using a colon.
Before the end of your for loop, try setting your collection to null. dc = null; This way you know for sure that you are getting a new collection in the next iteration.
Are any of your multi-value field values ambiguous? getAllDocumentsByKey(Vector) does partial matches. Unless you ever want that, I would recommend always using the second parameter and setting it to true, same always for getAllEntriesByKey().
An alternative, which will definitely perform better, would be to add a total column to the view. There's a performance hit of that on the view indexing, but you can then use a ViewNavigator with getColumnValues() and getNextSibling(). getCount() is extremely poor performing in LS and will almost certainly be as poorly performing in SSJS/Java. See this blog post from a few years ago http://www.intec.co.uk/why-you-shouldnt-count-on-a-notesviewnavigator/
If I understand that right: you want to count all values that are possible over an amount of documents to have a 5 value list with corresponsing 5 value counts, right?
You could loop through all docs, loop through all values and add entries to a HashMap with the value as key and an int as value (which should be increased everytime). Afterall you have a Map with 5 values holding the sums of each keys.
You will never get the right answer with getAllDocumentsByKey(). When document shows in one category, it will be missing from the collection of next category. That's the way it works.
Use ViewNavigator instead. Build it by category and simply count ViewEntries.

rowData not working as espected in repeat control

I have : <xp:repeat id="repeatColor" value="#{productcolors}"
var="rowData" indexVar="rownum" >
PROBLEM : rownum goes from 0 to the last correct value, but rowData is always the same
This repeat control is bound to a view "productcolors" , a view with a key on product code.
This view has a first column with the product code , ascending (for the key).
It also has a second and a third column with ascending multiple value fields.(second is framecolor, third is upholstery color)
The idea is that the repeat control goes through the different colors for the selected product, but it only shows the first one and does that the number of times (rownum increases correctly)that there are colors for the selected product.
EDIT :
So I have for example a product called "A" available in framecolors "1" "2" and "3"
When I am using the repeat control rownum changes from 0 to 2 but rowData is always the reference of framecolor "1". I don't know why rowData isn't changing.
When I use rowData.getUniversalID() I am getting 3 times the ID of the document containing the multiple value field with the 1 , 2 and 3 in it, which is I guess normal ? But how can I get a handle to those different values inside it ?
SECOND EDIT
I tried :
var testje:string = rowData.getUniversalID();
var db:NotesDatabase = session.getDatabase(database.getServer(),"product/colors.nsf");
var doc:NotesDocument = db.getDocumentByUNID(testje);
test = doc.getItemValueString("colorUpholstery");
The result is that "test" only holds the first item of the multiple value field "colorUpholstery" .
How is that possible ? I thought I would get the complete value of the "colorUpholstery" field ?
Maybe because I only have reader access(Publicaccess) to the colors.nsf database ?
It would be nice to see a little more code... like what's inside the repeat.. just to get a better feel for it to go along with your description of the Notes View.
rowData should be an XSPViewEntry... basically a NotesViewEntry... I suggest you first do something like rowData.getDocument().getUniversalId() to make sure it is iterating the documents correctly. I'm sure it is.
It sounds like you're trying to do something with a multi-value field.. are you also setting the view to use display multiple values as row entries? or whatever that setting is? That might get dicey if that's turned on. Not sure.
Again I'm not totally following what what the goal is but I would first test to make sure it is actually repeating the expected documents. then it's all about fine tuning.
EDIT: Ok... some thoughts based on your additional info:
I suspect that your problem is the use of the view setting "show multiple values as separate entries". Each is the same document really. So that's likely not helping you here. I'm still a little fuzzy on exactly what you want for the output. Is this from a "view page" of maybe products? a "form page" of a single product?
I ASSUME you want all the colors for a single product? And this is a lookup view right? so you're on your product "document" and now you want to list all the colors?
Assuming so...
Use SSJS and the object model. Do a lookup to find the SINGLE document that has the multi-value color field for your current product. then return to a repeat control something like:
lookupDoc.getItemValue("colorField")
I'm not 100% sure that's the correct syntax. The point is you can send a multi-value field to a repeat control and it will repeat it. Much easier then trying to use view tricks.
If your goal is to have a Repeat of multiple products.. and in side each "row" to show all the available colors then you're looking to have a nested repeat really... The outer repeat (outerData) to iterate over all the main products and inside that another repeat (innerData) for the colors. Inside that repeat code you use the "outerData" to get the multi-value field. Something like:
outerData.getDocument().getItemValue("colorField")
Assuming I'm understanding you correctly these are my suggestions.
I did do an example of nested repeats like this on an early NotesIn9. I believe it was this one: http://notesin9.com/index.php/2010/03/30/notes-in-9-show-14-repeats-repeated/
Maybe that will help.
Second Edit Response:
Based on the code you added you're using "doc.getItemValueString()" By design that will only get you the first value of a multi-value field. This is the same as saying in LotusScript:
doc.colorUpholstery(0)
or the less commonly used
doc.getItemValue("colorUpholstery")(0) ' I might have that wrong. I never really used it
Again if you want to make a list of all the colors I'd use a repeatControl and pass in:
doc.getItemValue("colorUpholstery") then your "rowData" for that repeat will be each value. I've seen others avoid the repeat and doing some javascript explode or implode type thing I believe. using "\N" or something as a separator for a new line. I just use a repeat. Easer for me to understand.
Again I THINK everything you need really is in NotesIn9 episode 14.

Resources