Monday, November 08, 2010 at 12:04 AM.
system.verbs.builtins.mainResponder.search.server.getResults
on getResults (adrSearch, adrSearchRequest=nil) {
<<Get the raw search results.
<<Changes:
<<8/8/02; 12:16:45 AM by JES
<<Respect config.mainResponder.search.prefs.hoursToCacheSearchResults.
<<10/29/99; 10:51:48 PM by PBS
<<Get the page table address in a try. It's possible that this script is running outside the rendering context.
<<10/1/99; 1:48:35 PM by PBS
<<Support for multiple sites. Instead of searching one site or all sites, you can search a specified set of sites.
<<9/13/99; 11:00:16 AM by PBS
<<Drop not just trailing s but also trailing S from keywords.
<<8/20/99; 12:01:36 PM by PBS
<<Don't ignore keywords of less than 3 characters: only ignore keywords in the stop words list.
local (i, j);
local (ctIgnored = 0);
local (results);
local (sizeSearchTable);
local (adrTable);
local (indexPath = adrSearch^.index);
local (termsTables);
new (tableType, @termsTables);
local (adrCache);
bundle { //set up the cache
local (siteName);
if not defined (temp.mainResponder.search) {
new (tableType, @temp.mainResponder.search)};
if not defined (temp.mainResponder.search.cache) {
new (tableType, @temp.mainResponder.search.cache)};
if not defined (temp.mainResponder.search.cache.[adrSearch^.index]) {
new (tableType, @temp.mainResponder.search.cache.[adrSearch^.index])};
if not defined (adrSearchRequest^.site) or adrSearchRequest^.site == "" {
siteName = "all"}
else {
siteName = adrSearchRequest^.site};
if not defined (temp.mainResponder.search.cache.[adrSearch^.index].[siteName]) {
new (tableType, @temp.mainResponder.search.cache.[adrSearch^.index].[siteName])};
adrCache = @temp.mainResponder.search.cache.[adrSearch^.index].[siteName].[adrSearch^.filteredSearchString]};
bundle { //delete cache if expired
if defined (adrCache^) {
local (hoursToCache = config.mainResponder.search.prefs.hoursToCacheSearchResults);
local (whenexpires = timeCreated (adrCache) + (hoursToCache * 60 * 60) );
if whenExpires < clock.now () {
delete (adrCache)}}};
on intersectTables (adrTables, adrResults) {
local (i, j);
local (sizeResults = sizeOf (adrResults^));
if sizeOf (adrTables^) > 0 {
if sizeResults > sizeOf (adrTables^ [1]) { //switch tables: performance enhancement
<<Switch the main table with the second term table.
<<This is a quick way to get a performance boost when the first term
<<is a super-common word like "Frontier."
local (tempTable = adrResults^);
adrResults^ = adrTables^ [1];
adrTables^ [1] = tempTable;
sizeResults = sizeOf (adrResults^)};
for i = sizeResults downTo 1 {
local (itemName = nameOf (adrResults^ [i]));
for j = 1 to sizeOf (adrTables^) {
if not defined (adrTables^ [j].[itemName]) {
delete (@adrResults^ [i]);
break};
adrResults^ [i] = adrResults^ [i] + adrTables^ [j].[itemName] + 4000}}};
return (true)};
if not defined (adrSearch^.ignoredList) {
adrSearch^.ignoredList = {}};
if not defined (adrSearch^.notFoundList) {
adrSearch^.notFoundList = {}};
for i = 1 to adrSearch^.countKeywords { //loop through keywords, finding matches
local (keyword = string.nthField (adrSearch^.filteredSearchString, ' ', i));
local (origkeyword = keyword);
<<PBS 8/20/99: don't ignore keywords of less than 3 characters.
<<if sizeOf (keyWord) < 3
<<ctIgnored++
<<adrSearch^.ignoredList [0] = origkeyword
<<continue
keyword = string.dropNonAlphas (keyword);
keyword = string.popTrailing (keyword, 's');
keyword = string.popTrailing (keyword, 'S'); //PBS 9/13/99: Drop trailing S also
if not (searchEngine.checkStopWords (keyword)) {
ctIgnored++;
adrSearch^.ignoredList [0] = origkeyword;
continue};
if not defined (adrCache^) {
local (firstLetter = keyword [1]);
if defined ([indexPath].index.[firstLetter].[keyword]) {
local (adrResults = @[indexPath].index.[firstLetter].[keyword]);
if i - ctIgnored == 1 {
adrSearch^.rawResults = adrResults^}
else {
new (tableType, @termsTables.[i]);
termsTables.[i] = adrResults^}}
else {
new (tableType, @adrSearch^.rawResults);
return (true)}}};
if not defined (adrCache^) {
if sizeOf (termsTables) < 1 and adrSearch^.countKeywords - ctIgnored > 1 {
new (tableType, @adrSearch^.rawResults);
return (true)}};
if not defined (adrCache^) {
intersectTables (@termsTables, @adrSearch^.rawResults)};
bundle { //handle "hot pages" -- pages that are often visited for this search string
if not defined (adrCache^) {
local (pta);
try {
pta = html.getPageTableAddress ()};
if defined (pta^.displaySearchString) {
local (adrHotPages = @[indexPath].hotPages);
if defined (adrHotPages^) {
local (adrSearchString = @adrHotPages^.[pta^.displaySearchString]);
if defined (adrSearchString^) {
local (i);
local (size = sizeOf (adrSearchString^));
for i = size downTo 1 {
if defined (adrSearch^.rawResults.[nameOf (adrSearchString^ [i])]) {
adrSearch^.rawResults.[nameOf (adrSearchString^ [i])] = adrSearch^.rawResults.[nameOf (adrSearchString^ [i])] + 1000;
if i == size { //top hit goes to top
adrSearch^.rawResults.[nameOf (adrSearchString^ [i])] = adrSearch^.rawResults.[nameOf (adrSearchString^ [i])] + 3000}};
if size - i == 4 { //only do top 5
break}}}}}}};
bundle { //filter the results by siteName if needed
if not defined (adrCache^) {
<<Filter the results based on a site name.
<<Also set adrScreen^.totalHits to the number of hits.
if defined (adrSearchRequest^.site) and (adrSearchRequest^.site != "") and (string.lower (adrSearchRequest^.site) != "all") {
local (sitesList = adrSearchRequest^.site); //PBS 10/1/99: search multiple sites
local (flAll = false);
if typeOf (sitesList) != listType {
sitesList = {sitesList}};
local (i);
for i = 1 to sizeOf (sitesList) {
sitesList [i] = string.lower (sitesList [i]);
if sitesList [i] == "all" {
flAll = true;
break}};
if not flAll {
local (indexName = adrSearchRequest^.indexName);
local (indexPath = Frontier.getSubFolder ("/ops/") + indexName);
for i = sizeOf (adrSearch^.rawResults) downTo 1 {
local (adrPageInfo, url, pageID);
pageID = nameOf (adrSearch^.rawResults [i]);
url = string.nthField (pageID, '@', 1);
adrPageInfo = @[indexPath].pageInfo.[pageID];
local (lowerPageSite = string.lower (adrPageInfo^.siteName));
if not (sitesList contains lowerPageSite) {
delete (@adrSearch^.rawResults [i])};
if lowerPageSite == "" {
delete (@adrSearch^.rawResults [i])}};
if sizeOf (adrSearch^.rawResults) < 1 {
return (mainResponder.search.server.nothingFound (@search))}}}}};
bundle { //sort results by relevancy
if not defined (adrCache^) {
local (oldTarget = target.set (@adrSearch^.rawResults));
target.set (@adrSearch^.rawResults);
table.sortBy ("Value");
try {target.set (oldTarget)};
adrCache^ = adrSearch^.rawResults;
setTimeCreated (adrCache, clock.now ())}
else {
adrSearch^.rawResults = adrCache^}};
<<Get the minimum relevancy ranking for AND searches.
adrSearch^.min = ((adrSearch^.countKeywords - ctIgnored) - 1) * 4000;
<<Get the total number of raw hits.
adrSearch^.totalHits = sizeOf (adrSearch^.rawResults);
bundle { //handle quoted items
local (s = adrSearch^.filteredSearchString);
if s contains "\"" {
loop {
if adrSearch^.totalHits == 0 {
break};
if s == "" {
break};
local (quotedItem);
local (ixquote = string.patternMatch ("\"", s));
local (ixquote2, remainder);
local (flQuote = false);
if ixquote < 1 {
break};
if ixquote == 1 {
flQuote = true};
try {
if s [ixquote - 1] == " " {
flQuote = true}};
if flQuote {
remainder = string.mid (s, ixquote + 1, infinity);
ixquote2 = string.patternMatch ("\"", remainder);
quotedItem = string.mid (remainder, 1, ixquote2 - 1);
quotedItem = string.lower (quotedItem);
if not (quotedItem contains " ") {
s = string.mid (remainder, ixquote2 + 1, infinity);
continue};
local (i);
for i = sizeOf (adrSearch^.rawResults) downTo 1 {
if adrSearch^.totalHits == 0 {
break};
local (j);
local (pageID = nameOf (adrSearch^.rawResults [i]));
<<local (adrPageInfo = mainResponder.search.getPageInfoAddress (pageID, adrSearch^.indicesFolder))
local (adrPageInfo);
adrPageInfo = @[indexPath].pageInfo.[pageID];
on checkString (adr) {
if defined (adr^) {
return (string.lower (adr^) contains quotedItem)};
return (false)};
if not (checkString (@adrPageInfo^.content)) {
if not (checkString (@adrPageInfo^.compactTitle)) {
if not (checkString (@adrPageInfo^.title)) {
delete (@adrSearch^.rawResults [i]); //the item doesn't contain the quoted string, delete it from the raw results
adrSearch^.totalHits--}}}}}
else {
break};
s = string.mid (remainder, ixquote2 + 1, infinity)}}};
return (true)}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.