MediaWiki:CRT Search.js: Difference between revisions
No edit summary |
No edit summary |
||
| Line 948: | Line 948: | ||
* Perform search with subobject conditions (inputs/mods) | * Perform search with subobject conditions (inputs/mods) | ||
* This requires a two-step query due to SMW limitations | * This requires a two-step query due to SMW limitations | ||
* | |||
* Strategy: Get all matching model names first, then paginate client-side | |||
* to avoid hitting SMW's query size/depth limits with huge OR queries | |||
*/ | |||
/** | |||
* Perform search with subobject conditions (inputs/mods) | |||
* Uses batched queries to avoid SMW query size limits | |||
*/ | */ | ||
function performSubobjectSearch(queryData, sortProperty) { | function performSubobjectSearch(queryData, sortProperty) { | ||
| Line 953: | Line 960: | ||
var subConditions = queryData.subobjectConditions; | var subConditions = queryData.subobjectConditions; | ||
// Build | // Build queries to find pages through their subobjects | ||
var subQueries = []; | var subQueries = []; | ||
subConditions.forEach(function(cond) { | subConditions.forEach(function(cond) { | ||
| Line 1,005: | Line 1,012: | ||
} | } | ||
var matchingModelsArray = Array.from(matchingModels).sort(); | |||
var | totalResults = matchingModelsArray.length; | ||
// Check if we have additional main conditions beyond just Category:CRT models | |||
var mainConditions = queryData.mainQuery.replace('[[Category:CRT models]]', '').trim(); | |||
// Fetch details for the matching models using batched queries | |||
fetchModelDetailsBatched(matchingModelsArray, mainConditions, sortProperty); | |||
// | }).catch(function(error) { | ||
var | isLoading = false; | ||
var | showError('Search failed. Please try again.'); | ||
console.error('Subobject query error:', error); | |||
}); | |||
} | |||
/** | |||
* Fetch model details using batched queries to avoid SMW size limits | |||
* @param {Array} allModels - All matching model names | |||
* @param {string} mainConditions - Additional SMW conditions (empty string if none) | |||
* @param {string} sortProperty - Property to sort by | |||
*/ | |||
function fetchModelDetailsBatched(allModels, mainConditions, sortProperty) { | |||
var api = new mw.Api(); | |||
// Get just the models for the current page | |||
var pageModels = allModels.slice(currentOffset, currentOffset + RESULTS_PER_PAGE); | |||
if (pageModels.length === 0) { | |||
isLoading = false; | |||
displayResults({ query: { results: {} } }); | |||
return; | |||
} | |||
// Split into small batches to avoid SMW query size limits | |||
// Use 25 models per batch to stay well under limits | |||
var BATCH_SIZE = 25; | |||
var batches = []; | |||
for (var i = 0; i < pageModels.length; i += BATCH_SIZE) { | |||
batches.push(pageModels.slice(i, i + BATCH_SIZE)); | |||
} | |||
// Build and execute batched queries | |||
var batchPromises = batches.map(function(batch) { | |||
// Use disjunction with || instead of separate [[]] OR [[]] to reduce query depth | |||
var disjunction = batch.join('||'); | |||
var query = '[[' + disjunction + ']]'; | |||
// Add main conditions if present | |||
if (mainConditions) { | |||
query = '[[Category:CRT models]]' + mainConditions + query; | |||
} | |||
return api.get({ | |||
action: 'ask', | action: 'ask', | ||
query: | query: query + | ||
'|?Has image#100px=image' + | '|?Has image#100px=image' + | ||
'|?Has brand=brand' + | '|?Has brand=brand' + | ||
| Line 1,027: | Line 1,075: | ||
'|?Has aspect ratio=aspect' + | '|?Has aspect ratio=aspect' + | ||
'|?Has TVL=tvl' + | '|?Has TVL=tvl' + | ||
'|limit=50' + | |||
'|limit=' | |||
'|format=json', | '|format=json', | ||
format: 'json' | format: 'json' | ||
}). | }); | ||
}); | |||
}). | Promise.all(batchPromises).then(function(batchResults) { | ||
// Merge results from all batches | |||
var mergedResults = {}; | |||
batchResults.forEach(function(data) { | |||
if (data.query && data.query.results) { | |||
Object.assign(mergedResults, data.query.results); | |||
} | |||
}); | |||
// Sort merged results by the specified property | |||
var sortedKeys = Object.keys(mergedResults).sort(function(a, b) { | |||
var aVal = getSortValue(mergedResults[a], sortProperty); | |||
var bVal = getSortValue(mergedResults[b], sortProperty); | |||
return aVal.localeCompare(bVal); | |||
}); | |||
var sortedResults = {}; | |||
sortedKeys.forEach(function(key) { | |||
sortedResults[key] = mergedResults[key]; | |||
}); | }); | ||
isLoading = false; | |||
displayResults({ query: { results: sortedResults } }); | |||
}).catch(function(error) { | }).catch(function(error) { | ||
isLoading = false; | isLoading = false; | ||
showError('Search failed. Please try again.'); | showError('Search failed. Please try again.'); | ||
console.error(' | console.error('Batch query error:', error); | ||
}); | }); | ||
} | |||
/** | |||
* Get sort value from a result for client-side sorting | |||
*/ | |||
function getSortValue(result, sortProperty) { | |||
if (!result || !result.printouts) return ''; | |||
var propMap = { | |||
'Has brand': 'brand', | |||
'Has model code': 'model', | |||
'Has screen size inches': 'size', | |||
'Has CRT type': 'type' | |||
}; | |||
var key = propMap[sortProperty] || 'brand'; | |||
var printout = result.printouts[key]; | |||
if (!printout || !printout[0]) return ''; | |||
var val = printout[0]; | |||
if (typeof val === 'object') { | |||
return String(val.fulltext || val.value || ''); | |||
} | |||
return String(val); | |||
} | } | ||