solr random fix
This commit is contained in:
@@ -218,43 +218,91 @@ export const storyApi = {
|
|||||||
hiddenGemsOnly?: boolean;
|
hiddenGemsOnly?: boolean;
|
||||||
}): Promise<Story | null> => {
|
}): Promise<Story | null> => {
|
||||||
try {
|
try {
|
||||||
// Create URLSearchParams to properly handle array parameters like tags
|
// Use proper Solr RandomSortField with dynamic field random_* for true randomness
|
||||||
const searchParams = new URLSearchParams();
|
// Each call generates a different random seed to ensure different random results
|
||||||
|
const randomSeed = Math.floor(Math.random() * 1000000);
|
||||||
|
const searchResult = await searchApi.search({
|
||||||
|
query: filters?.searchQuery || '*:*',
|
||||||
|
page: 0,
|
||||||
|
size: 1, // Only get one result - Solr RandomSortField considers entire dataset
|
||||||
|
authors: [],
|
||||||
|
tags: filters?.tags || [],
|
||||||
|
minRating: filters?.minRating,
|
||||||
|
maxRating: filters?.maxRating,
|
||||||
|
sortBy: `random_${randomSeed}`, // Use proper dynamic field with random seed
|
||||||
|
sortDir: 'desc',
|
||||||
|
|
||||||
if (filters?.searchQuery) {
|
// Advanced filters - pass through all filter options
|
||||||
searchParams.append('searchQuery', filters.searchQuery);
|
minWordCount: filters?.minWordCount,
|
||||||
}
|
maxWordCount: filters?.maxWordCount,
|
||||||
if (filters?.tags && filters.tags.length > 0) {
|
createdAfter: filters?.createdAfter,
|
||||||
filters.tags.forEach(tag => searchParams.append('tags', tag));
|
createdBefore: filters?.createdBefore,
|
||||||
}
|
lastReadAfter: filters?.lastReadAfter,
|
||||||
|
lastReadBefore: filters?.lastReadBefore,
|
||||||
|
unratedOnly: filters?.unratedOnly,
|
||||||
|
readingStatus: filters?.readingStatus,
|
||||||
|
hasReadingProgress: filters?.hasReadingProgress,
|
||||||
|
hasCoverImage: filters?.hasCoverImage,
|
||||||
|
sourceDomain: filters?.sourceDomain,
|
||||||
|
seriesFilter: filters?.seriesFilter,
|
||||||
|
minTagCount: filters?.minTagCount,
|
||||||
|
popularOnly: filters?.popularOnly,
|
||||||
|
hiddenGemsOnly: filters?.hiddenGemsOnly,
|
||||||
|
});
|
||||||
|
|
||||||
// Advanced filters
|
return searchResult.results && searchResult.results.length > 0
|
||||||
if (filters?.minWordCount !== undefined) searchParams.append('minWordCount', filters.minWordCount.toString());
|
? searchResult.results[0]
|
||||||
if (filters?.maxWordCount !== undefined) searchParams.append('maxWordCount', filters.maxWordCount.toString());
|
: null;
|
||||||
if (filters?.createdAfter) searchParams.append('createdAfter', filters.createdAfter);
|
|
||||||
if (filters?.createdBefore) searchParams.append('createdBefore', filters.createdBefore);
|
|
||||||
if (filters?.lastReadAfter) searchParams.append('lastReadAfter', filters.lastReadAfter);
|
|
||||||
if (filters?.lastReadBefore) searchParams.append('lastReadBefore', filters.lastReadBefore);
|
|
||||||
if (filters?.minRating !== undefined) searchParams.append('minRating', filters.minRating.toString());
|
|
||||||
if (filters?.maxRating !== undefined) searchParams.append('maxRating', filters.maxRating.toString());
|
|
||||||
if (filters?.unratedOnly !== undefined) searchParams.append('unratedOnly', filters.unratedOnly.toString());
|
|
||||||
if (filters?.readingStatus) searchParams.append('readingStatus', filters.readingStatus);
|
|
||||||
if (filters?.hasReadingProgress !== undefined) searchParams.append('hasReadingProgress', filters.hasReadingProgress.toString());
|
|
||||||
if (filters?.hasCoverImage !== undefined) searchParams.append('hasCoverImage', filters.hasCoverImage.toString());
|
|
||||||
if (filters?.sourceDomain) searchParams.append('sourceDomain', filters.sourceDomain);
|
|
||||||
if (filters?.seriesFilter) searchParams.append('seriesFilter', filters.seriesFilter);
|
|
||||||
if (filters?.minTagCount !== undefined) searchParams.append('minTagCount', filters.minTagCount.toString());
|
|
||||||
if (filters?.popularOnly !== undefined) searchParams.append('popularOnly', filters.popularOnly.toString());
|
|
||||||
if (filters?.hiddenGemsOnly !== undefined) searchParams.append('hiddenGemsOnly', filters.hiddenGemsOnly.toString());
|
|
||||||
|
|
||||||
const response = await api.get(`/stories/random?${searchParams.toString()}`);
|
|
||||||
return response.data;
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.response?.status === 204) {
|
if (error.response?.status === 404 || error.response?.status === 204) {
|
||||||
// No content - no stories match filters
|
// No content - no stories match filters
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
throw error;
|
|
||||||
|
// If random sorting fails, fallback to client-side approach
|
||||||
|
console.warn('Solr random sorting failed, falling back to client-side selection:', error.message);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fallback: get larger sample and pick randomly client-side
|
||||||
|
const fallbackResult = await searchApi.search({
|
||||||
|
query: filters?.searchQuery || '*:*',
|
||||||
|
page: 0,
|
||||||
|
size: 200, // Large enough sample for good randomness
|
||||||
|
authors: [],
|
||||||
|
tags: filters?.tags || [],
|
||||||
|
minRating: filters?.minRating,
|
||||||
|
maxRating: filters?.maxRating,
|
||||||
|
sortBy: 'createdAt',
|
||||||
|
sortDir: 'desc',
|
||||||
|
|
||||||
|
// Same advanced filters
|
||||||
|
minWordCount: filters?.minWordCount,
|
||||||
|
maxWordCount: filters?.maxWordCount,
|
||||||
|
createdAfter: filters?.createdAfter,
|
||||||
|
createdBefore: filters?.createdBefore,
|
||||||
|
lastReadAfter: filters?.lastReadAfter,
|
||||||
|
lastReadBefore: filters?.lastReadBefore,
|
||||||
|
unratedOnly: filters?.unratedOnly,
|
||||||
|
readingStatus: filters?.readingStatus,
|
||||||
|
hasReadingProgress: filters?.hasReadingProgress,
|
||||||
|
hasCoverImage: filters?.hasCoverImage,
|
||||||
|
sourceDomain: filters?.sourceDomain,
|
||||||
|
seriesFilter: filters?.seriesFilter,
|
||||||
|
minTagCount: filters?.minTagCount,
|
||||||
|
popularOnly: filters?.popularOnly,
|
||||||
|
hiddenGemsOnly: filters?.hiddenGemsOnly,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fallbackResult.results && fallbackResult.results.length > 0) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * fallbackResult.results.length);
|
||||||
|
return fallbackResult.results[randomIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (fallbackError: any) {
|
||||||
|
throw fallbackError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
1
frontend/tsconfig.tsbuildinfo
Normal file
1
frontend/tsconfig.tsbuildinfo
Normal file
File diff suppressed because one or more lines are too long
@@ -55,6 +55,9 @@
|
|||||||
<!-- Multi-valued string for URLs -->
|
<!-- Multi-valued string for URLs -->
|
||||||
<fieldType name="strings" class="solr.StrField" sortMissingLast="true" multiValued="true"/>
|
<fieldType name="strings" class="solr.StrField" sortMissingLast="true" multiValued="true"/>
|
||||||
|
|
||||||
|
<!-- Random sort field type for random ordering -->
|
||||||
|
<fieldType name="random" class="solr.RandomSortField" indexed="true"/>
|
||||||
|
|
||||||
<!-- Fields -->
|
<!-- Fields -->
|
||||||
|
|
||||||
<!-- Required Fields -->
|
<!-- Required Fields -->
|
||||||
@@ -90,6 +93,11 @@
|
|||||||
|
|
||||||
<!-- Default Search Field -->
|
<!-- Default Search Field -->
|
||||||
|
|
||||||
|
<!-- Dynamic Fields -->
|
||||||
|
|
||||||
|
<!-- Random sort dynamic field for generating random orderings -->
|
||||||
|
<dynamicField name="random_*" type="random" indexed="true" stored="false"/>
|
||||||
|
|
||||||
<!-- UniqueKey -->
|
<!-- UniqueKey -->
|
||||||
<uniqueKey>id</uniqueKey>
|
<uniqueKey>id</uniqueKey>
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,9 @@
|
|||||||
<!-- Single string for exact matching and faceting -->
|
<!-- Single string for exact matching and faceting -->
|
||||||
<fieldType name="string_facet" class="solr.StrField" sortMissingLast="true" docValues="true"/>
|
<fieldType name="string_facet" class="solr.StrField" sortMissingLast="true" docValues="true"/>
|
||||||
|
|
||||||
|
<!-- Random sort field type for random ordering -->
|
||||||
|
<fieldType name="random" class="solr.RandomSortField" indexed="true"/>
|
||||||
|
|
||||||
<!-- Fields -->
|
<!-- Fields -->
|
||||||
|
|
||||||
<!-- Required Fields -->
|
<!-- Required Fields -->
|
||||||
@@ -129,6 +132,11 @@
|
|||||||
|
|
||||||
<!-- Default Search Field -->
|
<!-- Default Search Field -->
|
||||||
|
|
||||||
|
<!-- Dynamic Fields -->
|
||||||
|
|
||||||
|
<!-- Random sort dynamic field for generating random orderings -->
|
||||||
|
<dynamicField name="random_*" type="random" indexed="true" stored="false"/>
|
||||||
|
|
||||||
<!-- UniqueKey -->
|
<!-- UniqueKey -->
|
||||||
<uniqueKey>id</uniqueKey>
|
<uniqueKey>id</uniqueKey>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user