Developer forum

Forum » Development » Mark product as updatet in Lucene when not using Product.Save()

Mark product as updatet in Lucene when not using Product.Save()

Martin Nielsen
Reply
Hi guys,

I would like to create products without using the API (The "Product.Save()" method), but still have Lucene index the products when running a "Partial update".
Is it possible to add a created/update product to the lucene queue?

Regards
 Martin




Replies

 
Pavel Volgarev
Reply
Hi Martin,

Yes, it's possible. Here is the code example:

using Dynamicweb.Searching;
using Dynamicweb.eCommerce;
using Dynamicweb.eCommerce.Common;
using Dynamicweb.eCommerce.Searching.Index;

......

var productID = "PROD123";
var variantID = "VO1.VO2";
var languageID = "LANG12";

// Getting meta-information about the standard eCommerce product indexer.
var info = IndexManager.Current.GetIndexerInfo(typeof(ProductIndexer));

// Getting the instance of the queue that corresponds to our index.
var queue = IndexManager.Current.GetIndexerQueue(info.Path);

// Creating new index entry.
var queueProduct = new ProductIndexEntry();

queueProduct.ID = productID;
queueProduct.VariantID = variantID;
queueProduct.LanguageID = languageID;

// A bit of magic here.
// In a later builds you would simply use "ProductIndexEntry.CreateQueueEntry".
queueProduct.UniqueID = string.Format("Products!{0}!{1}!{2}", productID, 
    (!string.IsNullOrEmpty(variantID) ? variantID : "0"),
    (!string.IsNullOrEmpty(languageID) ? languageID : Context.LanguageID));

// Putting the product into the queue (notice that every queue item must be associated with the indexer
// that is responsible fo pulling the actual data from the database when the index is being updated).
queue.Queue(new IndexerQueueItem(queueProduct, IndexerQueueItemState.Updated), info.ID);
A note regarding "ProductIndexEntry" and parameterless constructor:

There are couple overloads of the constructor (that takes either product ID or product instance) but you should avoid using them for performance reasons. When you pass product ID (as well as variant ID and language ID) the constructor will pull the product from the database but you don't need that because the queue needs only the IDs.

Passing the instance of the product to the constructor will also probably result in some additional database calls (since not all the product information might be available at that time).

For this particular cases we have a static method ProductIndexEntry.CreateQueueEntry that initializes only IDs. The problem with this method is that it's internal. I've changed the access modifier to "public" so the method will be available with the nearest release and you could simply do:

var queueProduct = ProductIndexEntry.CreateQueueEntry(productID, variantID, languageID);


Hope this helps.

-- Pavel
 
Martin Nielsen
Reply
Great, that looks pretty simple :-)

I'll be looking forward to it becoming a public method.

// Martin
 
Lars Hejgaard Sørensen
Reply

Hi Pavel,

I'm also importing products using the API, and I've implemented the suggestions in your post, so my code looks something like this:

using Dynamicweb.Searching;
using Dynamicweb.eCommerce;
using Dynamicweb.eCommerce.Common;
using Dynamicweb.eCommerce.Searching.Index;

......

var info = IndexManager.Current.GetIndexerInfo(typeof(ProductIndexer));
var queue = IndexManager.Current.GetIndexerQueue(info.Path);

foreach (var product in collection)
	var queueProduct = new ProductIndexEntry();
	queueProduct.ID = product.ID;
	queueProduct.VariantID = product.VariantID;
	queueProduct.LanguageID = product.LanguageID;
	queueProduct.UniqueID = string.Format("Products!{0}!{1}!{2}", productID,
		(!string.IsNullOrEmpty(product.VariantID) ? product.VariantID : "0"),
		(!string.IsNullOrEmpty(product.LanguageID) ? product.LanguageID : Context.LanguageID));
	queue.Queue(new IndexerQueueItem(queueProduct, IndexerQueueItemState.Updated), info.ID);
}

Dynamicweb.Searching.IndexManager.Current.UpdateIndex("Products", false);

The purpose is to have the index updated after all products have been imported, however, apparantly nothing is updated untill I force the update in MGMT center.

Do you have an idea of what's wrong?

BR.
Lars

 
Pavel Volgarev
Reply
Hi Lars,

To trigger the actual update do one of the following:

Synchronous (blocking) call:
Dynamicweb.Searching.IndexManager.Current.UpdateIndex("Products", false);
Asynchronous (non-blocking) call (not recommended though):
Dynamicweb.Searching.Management.IndexUpdateService.Current.CreateTask("Products", false);
-- Pavel

 
Pavel Volgarev
Reply
Hi Lars,

Sorry, didn't see the last line (where you triggering the update). What the error log says? What about the queue - is it empty after you run the code?

-- Pavel 
 
Lars Hejgaard Sørensen
Reply
Hi Pavel,

The server event log is empty. When the import is complete, 933 entries are pending for indexing, but in this case I only updated one product.

BR.
Lars
 
Pavel Volgarev
Reply
Hi Lars,

Could you attach the queue.xml so I can take a look at it (/Files/System/_search/Products/queue.xml)? Also, could you tell the ID of the product that you're updating?

Regarding those 933 items that are currently in the queue. This is probably due to the way the indexer processes the queue file - it doesn't touch (doesn't remove from the queue) those items that it cannot find in the source database. So when you actively manipulate product IDs (through the API) you can end up having the outdated information in your queue...

Anyway, I'd like to see your queue file. And if it's possible, could you provide the URL of the solution so I can log in and find out what's wrong?

-- Pavel
 
Lars Hejgaard Sørensen
Reply
Hi Pavel,

I sent you an email with the file.

BR.
Lars

 

You must be logged in to post in the forum