What is the easiest way doing the above, i.e. displaying date and time for the last update of the site content? is this done for example by going through (xslt) all nodes in umbraco.config and display the latest updateDate?
Finding the newest updated page in xslt can be done like this:
[code]
[/code]
where $RootNode is a picked node, and all folders are skipped. I does not appear to be optimal in terms of performance, but apparently caching will help you along the way - although I have not tested that.
You could write an xslt extension to query the internal lucene index and pull back last updated item that way, bit more work but would be lightening quick.
[code]
using System;
using System.Data;
using System.Configuration;
using System.Xml;
using System.Xml.XPath;
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using Lucene.Net.Store;
using umbraco;
namespace umbSearch.XSLTExtension
{
public class Search
{
private static string index {
get {
if (System.Web.HttpContext.Current != null)
{
return System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.StorageDirectory + "/umbSearch");
}
else {
return @"C:\code\umbraco\indexes\umbsearch";
}
}
}
#region public methods
///
/// call from xslt to do search useful for product searches etc going to be faster than xslt
/// query syntax http://lucene.apache.org/java/232/queryparsersyntax.html
/// test queries first using luke
///
/// lucene query
/// max number of results to return
///
public static XPathNodeIterator SearchByLuceneQuery(string Query, int MaxNoToReturn) {
XmlDocument xd = new XmlDocument();
xd.LoadXml("");
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addCDataNode(xd, "luceneQuery", Query));
try
{
IndexSearcher searcher = new IndexSearcher(index);
QueryParser qt = new QueryParser("contents", new StandardAnalyzer());
//todo set maxno to return
Hits hits = searcher.Search(qt.Parse(Query));
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addTextNode(xd, "results", hits.Length().ToString()));
if (hits.Length() > 0)
{
processHits(hits, xd, MaxNoToReturn);
}
searcher.Close();
}
catch (Exception ex) {
//add error node to query xml
}
XPathNavigator xp = xd.CreateNavigator();
return xp.Select("/search");
}
///
/// loop through lucene hits then build up xml
///
///
///
private static void processHits(Hits hits, XmlDocument xd, int MaxNoToReturn)
{
int count = hits.Length();
if (MaxNoToReturn >= count)
{
MaxNoToReturn = hits.Length();
}
for (int i = 0; i < MaxNoToReturn; i++)
{
Document doc = hits.Doc(i);
XmlNode x = createResultNode((i + 1).ToString(), xd);
//need to blag it to xmldoc coz original iterator was xpathdoc
XmlDocument newDoc = new XmlDocument();
newDoc.LoadXml(node.OuterXml);
//stick in the url for the item
XmlAttribute urlAttribute = newDoc.CreateAttribute("url");
urlAttribute.Value = url;
newDoc.DocumentElement.Attributes.Append(urlAttribute);
XmlAttribute scoreAttribute = newDoc.CreateAttribute("score");
make sure you change path to index to data_systemUmbracoIndexDontDelete in your root umbraco install dir. Use the luke to test the query and http://lucene.apache.org/java/232/queryparsersyntax.html to get query syntax.
display "last update" date in footer
Hi all,
What is the easiest way doing the above, i.e. displaying date and time for the last update of the site content? is this done for example by going through (xslt) all nodes in umbraco.config and display the latest updateDate?
Thanks in advance,
synsat
Hi synsat, you could check out this post:
http://forum.umbraco.org/yafpostst6507Finding-latest-updatepublish-time.aspx
Finding the newest updated page in xslt can be done like this:
[code]
[/code]
where $RootNode is a picked node, and all folders are skipped. I does not appear to be optimal in terms of performance, but apparently caching will help you along the way - although I have not tested that.
Thanks Tommy, I will check it out.
You could write an xslt extension to query the internal lucene index and pull back last updated item that way, bit more work but would be lightening quick.
[code]
using System;
using System.Data;
using System.Configuration;
using System.Xml;
using System.Xml.XPath;
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;
using Lucene.Net.Store;
using umbraco;
namespace umbSearch.XSLTExtension
{
public class Search
{
private static string index {
get {
if (System.Web.HttpContext.Current != null)
{
return System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.StorageDirectory + "/umbSearch");
}
else {
return @"C:\code\umbraco\indexes\umbsearch";
}
}
}
#region public methods
///
/// call from xslt to do search useful for product searches etc going to be faster than xslt
/// query syntax http://lucene.apache.org/java/232/queryparsersyntax.html
/// test queries first using luke
///
/// lucene query
/// max number of results to return
///
public static XPathNodeIterator SearchByLuceneQuery(string Query, int MaxNoToReturn) {
XmlDocument xd = new XmlDocument();
xd.LoadXml("");
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addCDataNode(xd, "luceneQuery", Query));
try
{
IndexSearcher searcher = new IndexSearcher(index);
QueryParser qt = new QueryParser("contents", new StandardAnalyzer());
//todo set maxno to return
Hits hits = searcher.Search(qt.Parse(Query));
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addTextNode(xd, "results", hits.Length().ToString()));
if (hits.Length() > 0)
{
processHits(hits, xd, MaxNoToReturn);
}
searcher.Close();
}
catch (Exception ex) {
//add error node to query xml
}
XPathNavigator xp = xd.CreateNavigator();
return xp.Select("/search");
}
///
/// loop through lucene hits then build up xml
///
///
///
private static void processHits(Hits hits, XmlDocument xd, int MaxNoToReturn)
{
int count = hits.Length();
if (MaxNoToReturn >= count)
{
MaxNoToReturn = hits.Length();
}
for (int i = 0; i < MaxNoToReturn; i++)
{
Document doc = hits.Doc(i);
XmlNode x = createResultNode((i + 1).ToString(), xd);
XmlElement elem = content.Instance.XmlContent.GetElementById(hits.Doc(i).Get("id"));
if (elem == null)
{
//its media node
XPathNodeIterator ni = umbraco.library.GetMedia(int.Parse(hits.Doc(i).Get("id")), false);
string url = hits.Doc(i).Get(umbSearch.Search.Settings.MediaFileNodeName);
float score = hits.Score(i);
elem = createMediaNode(ni, url, score).DocumentElement;
}
x.AppendChild(xd.ImportNode(elem, false));
xd.DocumentElement.AppendChild(x);
}
}
private static XmlDocument createMediaNode(XPathNodeIterator ni, string url, float score)
{
XmlNode node = ((IHasXmlNode)ni.Current).GetNode();
//need to blag it to xmldoc coz original iterator was xpathdoc
XmlDocument newDoc = new XmlDocument();
newDoc.LoadXml(node.OuterXml);
//stick in the url for the item
XmlAttribute urlAttribute = newDoc.CreateAttribute("url");
urlAttribute.Value = url;
newDoc.DocumentElement.Attributes.Append(urlAttribute);
XmlAttribute scoreAttribute = newDoc.CreateAttribute("score");
scoreAttribute.Value = (score * 100).ToString();
newDoc.DocumentElement.Attributes.Append(scoreAttribute);
return newDoc;
}
#endregion
#region private methods
///
/// loop through the hits and append to the xml document
///
///
///
private static void processHits(XmlDocument xd,Hits hits, int SimilarCount) {
int loopCount = SimilarCount;
int hitsCount = hits.Length();
if (hitsCount < SimilarCount)
{
loopCount = hitsCount;
}
for (int i = 0; i < loopCount; i++)
{
XmlNode node = xd.CreateElement("result");
node.InnerText = hits.Doc(i).Get("name");
node.Attributes.Append(createAttribute("id",hits.Doc(i).Get("id"),xd));
float score = hits.Score(i)*100;
node.Attributes.Append(createAttribute("score", score.ToString(), xd));
//only for non html will we get an acutal url
node.Attributes.Append(createAttribute("url", hits.Doc(i).Get("umbracoFile"), xd));
xd.DocumentElement.AppendChild(node);
}
}
private static XmlAttribute createAttribute(string name, string attribValue,XmlDocument xd) {
//hits.Score(i)
XmlAttribute attrib = xd.CreateAttribute(name);
attrib.Value = attribValue;
return attrib;
}
private static XmlDocument createDocument(string rootName)
{
XmlDocument xd = new XmlDocument();
xd.LoadXml("<" + rootName + "/>");
return xd;
}
///
/// adds default elements to the search results node
///
///
///
///
///
///
private static void primeSearchXmlDocument(XmlDocument xd, string searchQuery, string luceneQuery, int hitCount, string lastGooglePage)
{
xd.LoadXml("");
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addCDataNode(xd, "query", searchQuery));
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addCDataNode(xd, "luceneQuery", luceneQuery));
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addTextNode(xd, "results", hitCount.ToString()));
//results then stick in suggests node
if (hitCount == 0)
{
try
{
}
catch (Exception ex)
{
}
}
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addTextNode(xd, "currentPage", ""));
xd.DocumentElement.AppendChild(umbraco.xmlHelper.addTextNode(xd, "totalPages", lastGooglePage));
}
#endregion
}
}
[/code]
make sure you change path to index to data_systemUmbracoIndexDontDelete in your root umbraco install dir. Use the luke to test the query and http://lucene.apache.org/java/232/queryparsersyntax.html to get query syntax.
Regards
Ismail
is working on a reply...