Getting the last item in Sitecore content data - lucene

I am performing a search in which I have to get the 'ID' (field) of the last item stored in the sitecore/content/data/MyItem. The items stored in this folder are in 1000+ in number. I know Lucene search is by far efficient. I performed a Lucene Search to get the items based on the value like this:
using (IndexSearchContext searchContext = indx.CreateSearchContext())
{
var db = Sitecore.Context.Database;
CombinedQuery query = new CombinedQuery();
QueryBase catQuery = new FieldQuery("country", guidValueToSearch); //FieldName, FieldValue.
SearchHits results = searchContext.Search(catQuery); //Searching the content items by fields.
SearchResultCollection result = results.FetchResults(0, numOfArticles);
Here I am passing the guidValueToSearch for the items needs to be fetched for "country" field value. But I want to get the last item in the folder. How should I achieve this?

If you know you need the last childitem of /sitecore/content/data/MyItem, you could also use a more simple approach and get the parentItem and then retrieve the last child:
Item myItem = Sitecore.Context.Database.GetItem("/sitecore/content/data/MyItem");
Item lastItem = myItem.Children.Last();
The same could be done with Descendants instead of Children.

If you did want to implement it using search then have a look at this answer which explains how to extend the IndexSearchContext to have methods that accept a Lucene.Net.Search.Sort. You can then pass in the Sitecore.Search.BuiltinFields.Created or Sitecore.Search.BuiltinFields.Updated field (depending on what you are after).

Related

Lucene search or highlight field values in a document

The index document has some fields and each field has thousands of values. When the document is returned from the query, I want to further obtain the values of the "hit" contained in each field.
Currently, I use highlighter to loop through each field values
highlighter.setTextFragmenter(new SimpleFragmenter(1000));
final TokenStream tokenStream = analyzer.tokenStream(fieldName, new StringReader(fieldValue));
final CachingTokenFilter filter = new CachingTokenFilter(tokenStream);
final String fragment = highlighter.getBestFragment(filter, value);
if (fragment != null) {
//TODO
}
It works, but the performance is poor.
Is there a better way to achieve the same result and better performance.
Thanks in advance.
More details here
Each document has ten fields, field-1, field-2,...field-10, and each field has 1000 different values, such as field-1: apple, pear, banada,...
I use MultipleFieldQueryParser, when searching for "apple" for example, there are hits on field-1 and field-3, so in the first step I get the expected documents, and in the second step, I want to get fields-1: "apple", field-3: "2 apples" for the top hit document.
For the second step, I loop through each value of field-1, which means running highlight 1000 times. I think there may be a shortcut, such as applying a query or filter for the field-1 in the selected document and getting "apple", only one query is required

Dgrid selection mix-in issue with order

I've been having issues with the dgrid selection mix-in with multi selects.
Using the selection property (for example)
var selected = Object.keys(datatable.selection)
it returns an array of row ids as expected. However the ORDER of those ids seems to be "arbitrary". It seems perhaps that the order of selecting has an affect.
In any event, in the datatable, I want the selected rows to be returned in order that they display in the list, and they do not.
I can get them in the proper order using dojo.query(".dgrid-selected", datatable.domNode), and use the HTML element to get the row data, but this seems like a hack.
I cannot find a proper method to do this on the SitePen docs. Anyone?
I don't think that there is a direct way to do that. The Object.keys(datatable.selection) returns the array of ids in the order in which the rows are selected. You can use some built-in functions of d-grid and JS to achieve this. Below are the steps:
Get the id by Object.keys.
var selected = Object.keys(datatable.selection)
Create a list of objects comprising of id and rowIndex of element
Code:
var dataList= [];
for(var i=0; i< selected.length; i++){
dataList.push({id: selected[i], index: datatable.row(selected[i]).element.rowIndex});
}
Sort the list using index as the attribute:
dataList.sort(function(a, b){ return a.index- b.index; })
The resulting dataList would have the list of objects in order in which they appear in the grid.

How do you get Endeca to search on a particular target field rather than across all indexed fields?

We have an Endeca index configured across multiple fields of email content - subject and body. But we only want searches to be performed on the subject lines. Endeca is returning matches within the bodies too. How do you limit the search to the subject?
You can search a specific field or fields by specifying it (them) with the Ntk parameter.
Or if you wish to search a specific group of fields frequently you can set up an interface (also specified with the Ntk parameter), that includes that group of fields.
This is how you can do it using presentation API.
final ENEQuery query = new ENEQuery();
final DimValIdList dimValIdList = new DimValIdList("0");
query.setNavDescriptors(dimValIdList);
final ERecSearchList searches = new ERecSearchList();
final StringBuilder builder = new StringBuilder();
for(final String productId : productIds){
builder.append(productId);
builder.append(" ");
}
final ERecSearch eRecSearch = new ERecSearch("product.id", builder.toString().trim(), "mode matchany");
searches.add(eRecSearch);
query.setNavERecSearches(searches);
Please see this post for a complete example.
Use Search Interfaces in Developer Studio.
Refer - http://docs.oracle.com/cd/E28912_01/DeveloperStudio.612/pdf/DevStudioHelp.pdf#page=209

Rally custom grid with ((Parent = null) or (Parent.Name = 'xxxx'))

Can you create a custom User Story grid in Rally with the following query?
(((Parent = null) AND (Owner.Name = "dummy.name#email.com")) OR ((Parent.Name contains "Example") AND (Owner.Name = "dummy.name#email.com")))
Every time I try to do this it only returns results for the second part of the query. It seems like it cannot combine the Parent = null and the Parent.Name contains "Example".
Thanks for any feedback! I know that we could create two grids, but it would be nice to combine it into one.
This looks like a bug to me. Ignoring the owner portion of the query and taking just the Parent portions, per the title of your question: ((Parent = null) or (Parent.Name = 'xxxx')), it seems that I am also always seeing results that match the latter condition. If I switch the order, I get Parent-less stories. I'd recommend submitting a Case to Rally Support - rallysupport#rallydev.com - they can get this filed with the Rally developers.

jqGrid/NHibernate/SQL: navigate to selected record

I use jqGrid to display data which is retrieved using NHibernate. jqGrid does paging for me, I just tell NHibernate to get "count" rows starting from "n".
Also, I would like to highlight specific record. For example, in list of employees I'd like a specific employee (id) to be shown and pre-selected in table.
The problem is that this employee may be on non-current page. E.g. I display 20 rows from 0, but "highlighted" employee is #25 and is on second page.
It is possible to pass initial page to jqGrid, so, if I somehow use NHibernate to find what page the "highlighted" employee is on, it will just navigate to that page and then I'll use .setSelection(id) method of jqGrid.
So, the problem is narrowed down to this one: given specific search query like the one below, how do I tell NHibernate to calculate the page where the "highlighted" employee is?
A sample query (simplified):
var query = Session.CreateCriteria<T>();
foreach (var sr in request.SearchFields)
query = query.Add(Expression.Like(sr.Key, "%" + sr.Value + "%"));
query.SetFirstResult((request.Page - 1) * request.Rows)
query.SetMaxResults(request.Rows)
Here, I need to alter (calculate) request.Page so that it points to the page where request.SelectedId is.
Also, one interesting thing is, if sort order is not defined, will I get the same results when I run the search query twice? I'd say that SQL Server may optimize query because order is not defined... in which case I'll only get predictable result if I pull ALL query data once, and then will programmatically in C# slice the specified portion of query results - so that no second query occur. But it will be much slower, of course.
Or, is there another way?
Pretty sure you'd have to figure out the page with another query. This would surely require you to define the column to order by. You'll need to get the order by and restriction working together to count the rows before that particular id. Once you have the number of rows before your id, you can figure what page you need to select and perform the usual paging query.
OK, so currently I do this:
var iquery = GetPagedCriteria<T>(request, true)
.SetProjection(Projections.Property("Id"));
var ids = iquery.List<Guid>();
var index = ids.IndexOf(new Guid(request.SelectedId));
if (index >= 0)
request.Page = index / request.Rows + 1;
and in jqGrid setup options
url: "${Url.Href<MyController>(c => c.JsonIndex(null))}?_SelectedId=${Id}",
// remove _SelectedId from url once loaded because we only need to find its page once
gridComplete: function() {
$("#grid").setGridParam({url: "${Url.Href<MyController>(c => c.JsonIndex(null))}"});
},
loadComplete: function() {
$("#grid").setSelection("${Id}");
}
That is, in request I lookup for index of id and set page if found (jqGrid even understands to display the appropriate page number in the pager because I return the page number to in in json data). In grid setup, I setup url to include the lookup id first, but after grid is loaded I remove it from url so that prev/next buttons work. However I always try to highlight the selected id in the grid.
And of course I always use sorting or the method won't work.
One problem still exists is that I pull all ids from db which is a bit of performance hit. If someone can tell how to find index of the id in the filtered/sorted query I'd accept the answer (since that's the real problem); if no then I'll accept my own answer ;-)
UPDATE: hm, if I sort by id initially I'll be able to use the technique like "SELECT COUNT(*) ... WHERE id < selectedid". This will eliminate the "pull ids" problem... but I'd like to sort by name initially, anyway.
UPDATE: after implemented, I've found a neat side-effect of this technique... when sorting, the active/selected item is preserved ;-) This works if _SelectedId is reset only when page is changed, not when grid is loaded.
UPDATE: here's sources that include the above technique: http://sprokhorenko.blogspot.com/2010/01/jqgrid-mvc-new-version-sources.html