7a04fb667a40f234c3dd89a72698962edeb3fd7b larrym Thu Jun 10 20:24:01 2010 +0000 use trix search for simple search; style related code review changes per jim diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c index 53db8e7..6bbfbad 100644 --- src/hg/hgTracks/searchTracks.c +++ src/hg/hgTracks/searchTracks.c @@ -14,8 +14,9 @@ #include "web.h" #include "jksql.h" #include "hdb.h" +#include "trix.h" -static char const rcsid[] = "$Id: searchTracks.c,v 1.9 2010/06/03 05:52:42 larrym Exp $"; +static char const rcsid[] = "$Id: searchTracks.c,v 1.10 2010/06/10 20:24:01 larrym Exp $"; #define ANYLABEL "Any" #define METADATA_NAME_PREFIX "hgt.metadataName" @@ -52,17 +53,17 @@ (sameString(op, "contains") && containsStringNoCase(track->longLabel, str) != NULL)); } -static boolean isDescriptionMatch(struct track *track, char *str, struct hash *trackMetadata) -{ +static boolean isDescriptionMatch(struct track *track, char **words, int wordCount) // We parse str and look for every word ANYWHERE in track description (i.e. google style). // XXXX currently quite primitive; do stemming, strip html markup ?? // trackMetaData contains tracks already found via metadata searches. +{ boolean found = FALSE; -if(str && strlen(str)) +if(words) { char *html = track->tdb->html; - if(html == NULL || !strlen(html)) + if(isEmpty(html)) { // XXXX is there a cleaner way to find parent? struct trackDb *parent = track->tdb->parent; @@ -72,43 +73,35 @@ html = parent->html; } - if(html && strlen(html)) + if(!isEmpty(html)) { - char *tmp = cloneString(str); - char *val = nextWord(&tmp); - while (val != NULL) + int i; + for(i = 0; i < wordCount; i++) { + char *val = words[i]; if(strstrNoCase(html, val) == NULL) { - struct hashEl *el; found = FALSE; - for(el = hashLookup(trackMetadata, track->track); el != NULL; el = hashLookupNext(el)) - if(sameWord((char *) el->val, val)) break; - found = el != NULL; } else found = TRUE; - if(found) - val = nextWord(&tmp); - else - break; } } } return found; } -static int getTermList(struct sqlConnection *conn, char ***terms, char *type) -{ +static int getTermArray(struct sqlConnection *conn, char ***terms, char *type) // Pull out all term fields from ra entries with given type // Returns count of items found and items via the terms argument. +{ struct sqlResult *sr = NULL; char **row = NULL; char query[256]; struct slName *termList = NULL; int i, count = 0; -char **retval; +char **retVal; safef(query, sizeof(query), "select distinct val from metaDb where var = '%s'", type); sr = sqlGetResult(conn, query); @@ -120,21 +113,21 @@ sqlFreeResult(&sr); slSort(&termList, slNameCmpCase); count++; // make room for "Any" -retval = needMem(sizeof(char *) * count); -retval[0] = cloneString(ANYLABEL); +AllocArray(retVal, count); +retVal[0] = cloneString(ANYLABEL); for(i = 1; termList != NULL;termList = termList->next, i++) { - retval[i] = cloneString(termList->name); + retVal[i] = cloneString(termList->name); } -*terms = retval; +*terms = retVal; return count; } static struct slName *metaDbSearch(struct sqlConnection *conn, char *name, char *val, char *op) -{ // Search the assembly's metaDb table for var; If name == NULL, we search every metadata field. // Search is via mysql, so it's case-insensitive. -struct slName *retval = NULL; +{ +struct slName *retVal = NULL; char query[256]; struct sqlResult *sr = NULL; char **row = NULL; @@ -152,32 +145,32 @@ sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) { - slNameAddHead(&retval, row[0]); + slNameAddHead(&retVal, row[0]); } sqlFreeResult(&sr); -return retval; +return retVal; } static int metaDbVars(struct sqlConnection *conn, char *** metaValues) -{ // Search the assemblies metaDb table; If name == NULL, we search every metadata field. +{ char query[256]; struct sqlResult *sr = NULL; char **row = NULL; int i; struct slName *el, *varList = NULL; -char **retval; +char **retVal; safef(query, sizeof(query), "select distinct var from metaDb"); sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) slNameAddHead(&varList, row[0]); sqlFreeResult(&sr); -retval = needMem(sizeof(char *) * slCount(varList)); +retVal = needMem(sizeof(char *) * slCount(varList)); slNameSort(&varList); for (el = varList, i = 0; el != NULL; el = el->next, i++) - retval[i] = el->name; -*metaValues = retval; + retVal[i] = el->name; +*metaValues = retVal; return i; } @@ -206,6 +199,10 @@ char **metadataValue; struct hash *parents = newHash(4); boolean simpleSearch; +struct trix *ix; +char ixFile[HDB_MAX_PATH_STRING]; +char **descWords = NULL; +int descWordCount = 0; if(sameString(currentTab, "simpleTab")) { @@ -220,6 +217,8 @@ simpleSearch = FALSE; } +safef(ixFile, sizeof(ixFile), "/gbdb/%s/trackDb.ix", database); +ix = trixOpen(ixFile); getTrackList(&groupList, -2); slSort(&groupList, gCmpGroup); for (group = groupList; group != NULL; group = group->next) @@ -234,12 +233,11 @@ } } -hPrintf("
\n\n", hgTracksName()); +hPrintf("\n\n", hgTracksName()); webStartWrapperDetailedNoArgs(cart, database, "", "Track Search (prototype!)", FALSE, FALSE, FALSE, FALSE); hPrintf("\n", database); -fprintf(stderr, "currentTab: %s\n", currentTab); hPrintf("\n", currentTab); hPrintf("
\n" @@ -249,18 +247,18 @@ "\n" "
\n"); -hPrintf("\n", descSearch == NULL ? "" : descSearch); +hPrintf("\n", descSearch == NULL ? "" : descSearch); hPrintf("
\n" "
\n" "\n"); hPrintf("\n"); -hPrintf("\n", descSearch == NULL ? "" : descSearch); +hPrintf("\n", descSearch == NULL ? "" : descSearch); hPrintf("\n\n", nameSearch == NULL ? "" : nameSearch); +hPrintf("\n\n", nameSearch == NULL ? "" : nameSearch); hPrintf("\n"); hPrintf("\n\n\n"); @@ -348,11 +344,10 @@ } hPrintf("
Description:contains
andTrack Name:\n"); cgiMakeDropListFull("hgt.nameOp", op_labels, ops, ArraySize(ops), nameOp == NULL ? "contains" : nameOp, NULL); -hPrintf("
andGroupis\n"); @@ -313,8 +311,6 @@ metadataValue[1] = ANYLABEL; } -fprintf(stderr, "numMetadataSelects: %d: %d\n", numMetadataSelects, numMetadataNonEmpty); - if(metaDbExists) { int i; @@ -340,7 +336,7 @@ cgiMakeDropListClassWithStyleAndJavascript(buf, metaValues, count, metadataName[i], NULL, NULL, "onchange=metadataSelectChanged(this)"); hPrintf("is\n"); - len = getTermList(conn, &terms, metadataName[i]); + len = getTermArray(conn, &terms, metadataName[i]); safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1); cgiMakeDropListFull(buf, terms, terms, len, metadataValue[i], NULL); hPrintf("
\n"); -// hPrintf("+"); hPrintf("
\n
\n"); -hPrintf("\n", searchTracks); +hPrintf("\n", searchTracks); hPrintf("\n"); hPrintf("
\n"); @@ -360,13 +355,62 @@ descSearch = NULL; if(groupSearch != NULL && sameString(groupSearch, ANYLABEL)) groupSearch = NULL; -if(doSearch && ((nameSearch != NULL && strlen(nameSearch)) || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty)) + +if(!isEmpty(descSearch)) + { + char *tmp = cloneString(descSearch); + char *val = nextWord(&tmp); + struct slName *el, *descList = NULL; + int i; + + while (val != NULL) + { + slNameAddTail(&descList, val); + val = nextWord(&tmp); + } + descWordCount = slCount(descList); + descWords = needMem(sizeof(char *) * descWordCount); + for(i = 0, el = descList; el != NULL; i++, el = el->next) + descWords[i] = strLower(el->name); + + } + +if(doSearch) + { + if(simpleSearch) + { + struct trixSearchResult *tsList; + struct hash *trackHash = newHash(0); + + // Create a hash of tracks, so we can map the track name into a track struct. + for (group = groupList; group != NULL; group = group->next) + { + struct trackRef *tr; + for (tr = group->trackList; tr != NULL; tr = tr->next) + { + struct track *track = tr->track; + hashAdd(trackHash, track->track, track); + struct track *subTrack = track->subtracks; + for (subTrack = track->subtracks; subTrack != NULL; subTrack = subTrack->next) + hashAdd(trackHash, subTrack->track, subTrack); + } + } + for(tsList = trixSearch(ix, descWordCount, descWords, TRUE); tsList != NULL; tsList = tsList->next) + { + struct track *track = (struct track *) hashFindVal(trackHash, tsList->itemId); + refAdd(&tracks, track); + tracksFound++; + } + slReverse(&tracks); + } + else if(!isEmpty(nameSearch) || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty) { // First do the metaDb searches, which can be done quickly for all tracks with db queries. struct hash *matchingTracks = newHash(0); struct hash *trackMetadata = newHash(0); struct slName *el, *metaTracks = NULL; int i; + for(i = 0; i < numMetadataSelects; i++) { if(!isEmpty(metadataValue[i])) @@ -408,7 +452,7 @@ { struct track *track = tr->track; if((isEmpty(nameSearch) || isNameMatch(track, nameSearch, nameOp)) && - (isEmpty(descSearch) || isDescriptionMatch(track, descSearch, trackMetadata)) && + (isEmpty(descSearch) || isDescriptionMatch(track, descWords, descWordCount)) && (!numMetadataNonEmpty || hashLookup(matchingTracks, track->track) != NULL)) { tracksFound++; @@ -420,7 +464,7 @@ for (subTrack = track->subtracks; subTrack != NULL; subTrack = subTrack->next) { if((isEmpty(nameSearch) || isNameMatch(subTrack, nameSearch, nameOp)) && - (isEmpty(descSearch) || isDescriptionMatch(subTrack, descSearch, trackMetadata)) && + (isEmpty(descSearch) || isDescriptionMatch(subTrack, descWords, descWordCount)) && (!numMetadataNonEmpty || hashLookup(matchingTracks, subTrack->track) != NULL)) { // XXXX to parent hash. - use tdb->parent instead. @@ -435,6 +479,9 @@ } } slSort(&tracks, gCmpTrack); + } + } + if(tracksFound) { hPrintf("

%d tracks found:

\n", tracksFound); @@ -442,7 +489,7 @@ hButton("submit", "save"); hButtonWithOnClick("hgt.ignoreme", "show all", "show all found tracks", "alert('show all not yet implemented'); return false;"); hPrintf("\n"); - hPrintf("\n"); + hPrintf("\n"); struct slRef *ptr; while((ptr = slPopHead(&tracks))) { @@ -463,13 +510,10 @@ trackDbSetting(track->tdb, "onlyVisibility")); } hPrintf("\n"); - hPrintf("\n", track->shortLabel); + hPrintf("\n"); hPrintf("\n", trackUrl(track->track, NULL), track->longLabel); - // How do we get subtrack's parent? - struct track *parent = NULL; - if(hashLookup(parents, track->track) != NULL) - parent = (struct track *) hashLookup(parents, track->track)->val; - hPrintf("\n", parent != NULL ? parent->longLabel : track->group != NULL ? track->group->label : ""); hPrintf("\n"); } hPrintf("

NameDescriptionGroup

NameDescription
%s%s", track->shortLabel); + compositeMetadataToggle(database, track->tdb, "...", TRUE, FALSE); + hPrintf("%s%s
\n"); @@ -478,8 +522,8 @@ } else { + if(doSearch) hPrintf("

No tracks found

\n"); } - } webEndSectionTables(); }