Sitecore ContentSearch by field and relevance - sitecore

I'm using Sitecore 8 MVC .net 4.5. I have boolean field Is Sponsored and I need to order all items such as first with field Is Sponsored = true and by relevance. I found if I add order by Is_Sponsored I'm losing relevance order. So my question is: is there a way to include relevance in existing ordering?

the above method will work fine if you have only a limited amount of documents as you must read all documents from the index.
You can sort by the field SCORE to sort by the sort - so your sort order would be isSponsered, SCORE. This should work as far as I remember - but I have not validated it.
else - more to solr and you will have a number of options to solve this.

You could skip the boolean check in your query and run a regular query with the right relevance order coming back. Then filter down that result set by the boolean value into two separate collections.
var results = queryable.Where(predicate).ToList();
Then:
var sponsored = results.Where(i => i.IsSponsored);
var notSponsored = results.Where(i => !i.IsSponsored);
Then join the collections.

Related

Total number of documents in pysolr

How can I get the total number of documents matching the given query. I have use the query below:
result = solr.search('ad_id : 20')
print(len(result))
Since the default returning value is '10', the output is only 10, but the count is 4000. How can I get the total number of counts?
The results object from pysolr has a hits property that contains the total number of hits, regardless of how many documents being returned. This is named numFound in the raw response from Solr.
Your solution isn't really suitable for anything with a larger dataset, since it requires you to retrieve all the documents, even if you don't need them or want to show their content.
The count is stored in numFound variable. Use the code below:
result = solr.search('ad_id : 20')
print(result.raw_response['response']['numFound'])
As #MatsLindh mentioned -
result = solr.search('ad_id : 20')
print(result.hits)
Finally got the answer:
Added rows=1000000 at the end of the query.
result = solr.search('ad_id : 20', rows=1000000)
But if the rows are greater than this the number should be changed in the query. This might be a bad solution but works.
If anyone has a better solution please do reply.
If you just want the total number of items that satisfy your query, here is my Python3 code (using the pysolr module):
collection='bookindex' # or whatever your collection is called
solr_url = f"http://{SOLR_HOST}/solr/{collection}"
solr = pysolr.Solr(url=solr_url, timeout=120, always_commit=True)
result = solr.search("*:*", rows=0);
return result.hits
This queries for all documents (":") -- 315913 in my case -- but you can narrow that to suit your requirements. For example, if I want to know how many of my book entries have title:pandas I can search("title:pandas", rows=0) and get 41 as the number that have pandas in the title. By setting rows=0 you're letting Solr know that it need not format any results for you but you just return the meta information, and thus much more efficient than setting a high limit on rows.

Ordering Sitecore search results

I have a IQueryable<T> object as search results object.
I apply the filtering and sorting on this search object.
Before I call the GetResults(), I want to order the results based on one of the field's (Fieldname - Priority) value. So for all the items in the IQueryable<T> object, I want to order them desc by Priority field, so all the items which has a value for that field stay at the top and the rest are at the bottom.
I have the fieldmap entry for Priority field.
search.OrderByDescending(i => !string.IsNullOrEmpty(i.GetItem().GetFieldValue("Priority")))
The above command doesn't work. Apparently, I can't use Sitecore extension methods with IQueryable?
If I convert search.ToList(). Do the ordering and then convert it back to AsQueryable(), I get the following error:
There is no method 'GetResults' on type 'Sitecore.ContentSearch.Linq.QueryableExtensions'
that matches the specified arguments
Is there a neat and quick way to get around this?
Cheers
I think you just need to add your field to your SearchResultItem and mark it as an int. I am making the assumption that the field is an int. Make a custom class that inherits SearchResultItem.
public class CustomSearchResultItem : SearchResultItem
{
[IndexField("Priority")]
public int Priority { get; set; }
}
Then use it in your search. Finally order by it.
using (var context = ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var results = context.GetQueryable<CustomSearchResultItem>().Where(prod => prod.Content.Contains("search box text").OrderByDescending(t => t.Priority);
}
Some data found here.
http://www.sitecore.net/learn/blogs/technical-blogs/sitecore-7-development-team/posts/2013/10/sorting-and-ordering-results.aspx
You can order search results using multiple fields by using the OrderByDescending combined with ThenByDescending. So you would need to order by Priority and then by [Name|Date|Whatever].
I want to order them desc by Priority field, so all the items which has a value for that field stay at the top and the rest are at the bottom.
I sort them first on the criteria chosen by the user - like Name, Date created etc. Once I get the results back, I need to order them by priority field
You are conflicting yourself in the questions and comments. If you want the results with priority first and then by user selected results then the following will work:
query = dataQuery.OrderByDescending(i => i.Title).ThenByDescending(i => i["Priority"]);
var results = query.GetResults().Hits.Select(h => h.Document);
There was a bug in earlier version of Sitecore which meant that the ThenBy clause will be added before the OrderBy clause hence it is added in reverse above. You may want to check if this is fixed in the current version. If so simply change your query to:
query = dataQuery.OrderByDescending(i => i["Priority"]).ThenByDescending(i => i.Title);
You don't have to add the field to your SearchResultItem if you just want to order by it, only if you need the actual value of that field returned to as well.
If you need to order by a custom user supplied value then you can pass in i => i["whatever-field-the-user-has-selected"] instead of i.Title.
You can find more info in this blog post.

how to match a field name with another field name

I have two fields that run throughout a website that I would like to match so that when a user inputs a value either of the fields, it will match the other field. I'm using Sitecore Rocks and am trying to use a query to do this.
select ##h1#, ##Title#
from /sitecore/Content/Home//*[##h1# !="##Title#"];
update set ##h1# = ##Title# from /sitecore/Content/Home//*[##Title# = "<id>"];
What am I missing here?
This article talks about tapping in to the item:saving event which allows you to compare the fields values of the item before and after the changes:
http://www.sitecore.net/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2010/11/Intercepting-Item-Updates-with-Sitecore.aspx
Using this, you can determine which field has been amended, then change the other to match.
I've had to do something similar to this when a new field was added, and we wanted to set the initial value equal to an existing field. It may be a bug in Sitecore Rocks, but I found it would only update a field when a static value was part of the query.
When I ran ##h1# = ##Title#, the query analyzer would return the correct number of items updated, but no values were actually updated. However, ##h1# = '<id>' worked perfectly. After trying a number of things, I found this did what I wanted.
update set ##h1# = '' + ##Title# from /sitecore/Content/Home//*[##Title# = "<id>"];
I hope that helps.

Sitecore Fast Query select attribute values

Is there a way by using XPath Builder under Developer Center inside Sitecore Shell (a Fast Query interface) to select a particular attribute from an item. Example:
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/#id
I would expect to see a collection of id's to be returned where id is an attribute of an item. If yes is it possible to extract an attribute with a space bar? Example:
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/#more info
EDIT
The thing that I want to achieve is to get a collection of items (I have few hounded items here), not one particular item. That's why I am not interested in adding additional conditions, like specific item id or title. I want to see a collection of values of a specific attribute. As in example showed above, I want to see a collection of values that are assign to 'more info' attribute. Once again I am expecting to see few hounded different values that are set to 'more info' attribute.
EDIT2
There is a problem with a production, a critical stuff. There is no access to it other then thru Sitecore shell, but I don't have permissions to add/install additional packages. I know how to get this info by implementing custom code, or queering db directly, but I simply do not have permission to do it. Guys that will be able to grant me need credentials will wake up in 6 hours, so I was hoping to do whatever I can to analyse the situation. I would accept Maras answer if it was an answer not a comment - there is no way I can do it using fast query. thanks for help.
Try using #
/sitecore/content/Home/Products/*[##templatename = 'Product Group']/##more info#
This is the way around when selecting items with fields that contain spaces. Having said that I don't know if you would be able to get a specific result or not for your specific question but give it a try.
For example, consider this query which returns Product S1
fast:/sitecore/content/home/*[#Title = 'Item 1' and ##templatename = 'Product Group1']//*[#Title = 'Product S1' and ##id = '{787EE6C5-0885-495D-855E-1D129C643E55}']
However, if you place the special attribute (i.e. ##id) at the beginning of the condition, the query will not return a result.
fast:/sitecore/content/home/*[##templatename = 'Product Group1' and #Title = 'Product S1']//*[##id = '{787EE6C5-0885-495D-855E-1D129C643E55}' and #Title = 'Product S1']
Remember this, Sitecore Fast Query only supports the following special attributes:
##id
##name
##key
##templateid
##templatename
##templatekey
##masterid
##parentid
Let us know if this helps.

Django, how to filter for a range of rows then pick the one with max date?

Goal:
In here I am filtering for deals with the given id and from those I would like to pick the one with the latest date.
contact.deal_set.filter(deal_id=deal_id).aggregate(Max('deal_start_datetime'))
However this only gives back a dictionary with the max date in it. I need the row though.
What am I doing wrong?
Use the .latest method provide for django query sets.
For example in your particular case:
contact.deal_set.filter(deal_id=deal_id).latest('deal_start_datetime')
Django Documentation: https://docs.djangoproject.com/en/dev/ref/models/querysets/#latest
Use this
contact.deal_set.filter(deal_id=deal_id).order_by('-deal_start_datetime')
This will sort queryset by deal_start_datetime in reverse, 0th element is the latest one, you can get it as
latest_contact = contact.deal_set.filter(deal_id=deal_id).order_by('-deal_start_datetime')[0]