Efficient way to grab all items form ContentSearchManager SearchIndex in Sitecore? - sitecore

using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
var items = context.GetQueryable<SearchResultItem>()
.Where(item => item.TemplateId == _templateId)
.ToList();
var resultList = new List<MediaItem>();
I then go through and use conditionals to filter the results more and add them to resultList.
I add them to the list with (MediaItem)x.GetItem();
I have terrible performance, which I am sure is caused by GetItem querying the database 10,000s of times.
I need to have the results as a MediaItem due to needing to edit the fields in these items.
How can I avoid querying Sitecore for each item with GetItem() ?
Thanks,
Sitecore Noob
I tried using .GetItem() with poor performance. I also tried researching how to get back Items instead of SearchResultItem

Yes, this would be a very slow and ineffective way of loading the needed items, since you're basically loading references to all media items of the given type into memory from Solr (GetQueryable<T>) and then load everything again from the database through .GetItem(). But the pattern you're trying isn't too far off actually.
Using the SearchContext, you should do the filtering in where you get all items references you need, letting Solr do the computation. I.e. not the 10,000s of items, just the ones you're editing. Once you get the filtered result back from Solr, you perform the .GetItem() on the items you want to work with. Always check that the item (and version) actually exists after a .GetItem() since the Solr index can sometimes be out of sync with the database, so a Solr response can in rare cases reference an item that doesn't exist.
How you should write the Solr query is a bit hard to describe without knowing more details about what filters you need. In general, I'd recommend using the SolrNet API directly instead of going through the ContentSearchManager wrapper. It's sometimes hard to understand what the search manager does under the hood and you basically need to monitor the Search.log in order to verify that your code does what it's supposed to do. A small mistake in the .Where() could cause the entire media library to be loaded into memory and you'll experience the same performance issue again as you have right now. With the query you have today, it's worth noting the difference between the underlying _template and _templates index fields, as the first one (that's used in your sample code) will return items of exactly that given template while the later one will also include all items inheriting from that template.

Related

How to not lose hasMany changes on Ember query?

In my application, I search for documents with query.
Then I edit one attribute in a single document, and then I call search query again.
Result is OK, I see document still in a dirty state with changed attribute.
Then I again pick one of documents and edit its hasMany relation (from 2 items to 4 items). And then I call search query again.
Result is NOT OK, hasMany relation change is lost/disposed/rollbacked.
Is there a way so Ember query (i guess it's some Ember internal reload) does not rollback not saved relation changes ?
I am using Ember 2.9.1
For now i have no other way than prohibit any filter query actions or route actions anything that could call query again, since that would cause lost data that user set.
Ember's store.query method always refetches the models from the backend (unlike the find* methods). With a query, it's the only way to make sure you have the most up-to-date data (and that the models loaded into the store are still valid). Even in your instance, you may run into unexpected results if you change the data such that it no longer meets your query criteria.
If you would like to keep edits around between queries, I would recommend making a copy of all models which are dirty (check the hasDirtyAttributes attribute). You can gather them with peekAll. Once copied, you can then make the query and patch the records by ID. Perhaps by using Ember.assign.
Even using that method, I would still think that you will get into trouble tracking the changes and making sure the records stay consistent with your query. Like what do you if that record wasn't returned (deleted on the server or no longer meets your criteria)? Do you drop your edits? What if you have a conflict between the data from the server and your local version (e.g. another user patched the hasMany relationship that the other user is now querying and modifying)?
ember-changeset seems like it could be useful here. However, it's not obvious how to get a ChangeSet to apply to a new instance of the same model. Though it may be possible to keep a snapshot and match them up manually. However, you still run into data consistency issues.

How to implement model's read/unread property

I'm writing a Django application where an user can view multiple List objects, which contains several ListItems.
What I want is to keep track of of read/unread property for each ListItem object for each user. A List object is indexed using Solr.
I have one suggestion but I feel like it's not the ideal one.
1) Since each ListItem contains a timestamp when it was created. I could store the last viewed timestamp per List/User and query for all items in that list that are newer than this timestamp, that would allow me to get unread articles for a given user in a list.
What I don't like about this that some sites can keep track of (r)ead/(u)nread property where the list looks like this ruuuururururuuur. My solution can only mark articles from certain timestamp as read like rrrrrrruuuuuu.
2) I was also thinking about taking advantage of Solr index, but indexing user specific data that often is in my opinion definitely a bad idea. While browsing the net, I've also seen some suggestions to create a separate index for user related data? Would that be a way to go?
What is the best practice for implementing such a solution? Any help, suggestion or links to relevant articles would be appreciated.

Ember query-params-new for multiple objects

I'm using query parameters for paging and filtering. query-params-new provides a relatively convenient way to manage array returned from route.model.
But now I've got a page with a single object (f.e. group) as model, and a list of dependent objects (f.e. users in group), displayed at the same time. List should have paging.
The problem is that I dont know where I should put request for the list. Query parameters, needed for constructing list query, are only available in route.model method and in controller as properties.
Now I'm trying to find a proper way to get both object and list with paging in same route/controller. None of the ways I could invent, like combining them both into single object in route.model or requesting list from controller's observes function, seem right and clean. Currently I've stopped on saving query parameters in route.model and using them in route.setupController for second request, but that is a hack obviously.
I'm just looking for the right approach, without fighting framework.

Performance issue when typing into search input when retrieving objects from store

I have a search field, which lets the user search books (filters records, which are retrieved with ember-data).
I have found that any access the store from the results computed property within my component (see jsbin) makes the typing into the search field very slow (noticeable on my PC, and terrible on smartphone).
Here is a screenshot of the Timeline pane when typing a search query. The displayed part show that every keypress causes A LOT of layout (the search field seems to rerendered on every keypress). I also provide the exported timeline which you can load into your dev tools as explained here
I have tried to recreate the issue in a jsfiddle, but it seems to work just fine. The difference might be that in the jsbin I am using fixtures, while in my app I retrieve data from a real API.
I don't understand what is causing this behavior. It may be hard to come to any conclusion from the data I can provide, but does anyone have any ideas? Has anyone experienced similar performance issues?
Update 2014-03-01
I should note that the performance hit only happens if the results computed property contains a call to the store. If I replace it with any other thing (like just returning [], or some random async method -- like $.get) it not display this performance hit.
Additionally, I should make it clear (in case you didn't read the code), that the results computed property is not called on every keypress, but only when the search is submitted.
This is not a Ember/Ember-data bug, but apparently a Google Chrome bug.
I have created a new question regarding the issue here

Ember.js views dealing with existing DOM content

Quite often we deal with lists of things on our site. These initially get loaded with the rest of the page from the server. However, any updates received we would like to update these lists using Ember.
All of the examples I have seen so far with Ember views deal with controlling content on a page that has always been created purely by Ember. What options are there for dealing with DOM elements that already exist on the page with Ember views?
There has been some discussion around this idea here: https://github.com/emberjs/ember.js/issues/563
In the current situation two approaches come to my mind:
Replace the static rendered list with an Ember.CollectionView as soon as all list items are available to ember as data objects (e.g through ember-data)
Use plain old jQuery to append the latest updates at the beginning / end of the list
I guess it depends on how complex your list items and the updating logic is. If updates need reordering of items and your list needs complex interaction, the first approach using ember might be better suited, although there could be a "flickering" of content while the lists are replaced. The second approach is much simpler but also limited. I would only use jQuery for appending / prepending content. Still, if the lists are simple it would be overkill to even use ember in this case.