Solr Development Troubleshooting
This document covers common Solr development issues, fixes, and troubleshooting guides.
SOLR Filter AND Logic Fix
Problem
When sending multiple filter parameters to SOLR search, filters were using OR logic instead of AND logic. This caused MORE results with more filters (union) instead of FEWER results (intersection/drilling down).
Example:
?status=active&category=featured
Expected: Items that are BOTH active AND featured (fewer results) Actual: Items that are active OR featured (more results) ❌
Root Cause
There was a key mismatch in the buildSolrQuery() method:
// Line 2163 - WRONG KEY
$solrQuery['filters'] = $filterQueries;
But executeSearch() was looking for:
// Line 3259 - DIFFERENT KEY
if ($key === 'fq' && is_array($value)) {
Result: Filters were never being passed to SOLR at all! No filtering was happening, so results weren't being narrowed down.
Solution
Changed line 2165 to use the correct key:
// **CRITICAL FIX**: Use 'fq' key (not 'filters') so executeSearch() can find them
// Multiple fq parameters are ANDed together by SOLR (drilling down)
$solrQuery['fq'] = $filterQueries;
Now filters are properly passed as multiple fq parameters to SOLR:
fq=status:active&fq=category:featured
SOLR automatically ANDs multiple fq parameters together.
How Filtering Works Now
Single Value Filters (AND Logic)
?status=active&category=featured
Creates:
fq=status:active
fq=category:featured
Result: active AND featured (fewer results) ✅
Array Value Filters (OR Logic within field)
?status[]=active&status[]=pending
Creates:
fq=(status:active OR status:pending)
Result: active OR pending (more results for that field) ✅
Mixed Filters
?status[]=active&status[]=pending&category=featured
Creates:
fq=(status:active OR status:pending)
fq=category:featured
Result: (active OR pending) AND featured ✅
Testing
After deploying, test with multiple filters:
- Single filter: Should return subset
- Two filters: Should return smaller subset (drill down)
- Three filters: Should return even smaller subset (drill down further)
More filters = fewer results = drilling down ✅
Debug Logging
Added extensive debug logging to diagnose filter issues:
- Logs incoming query structure
- Logs each filter being built
- Logs final filter queries sent to SOLR
- Check logs if filtering still doesn't work as expected
Date Fixed: 2024-10-14
UUID Label Resolution for Facets
Problem Statement
When faceting on object fields that contain UUIDs (references to other objects), the facet labels were displaying raw UUID strings instead of human-readable names. This made facets unfriendly for frontend users and also prevented proper alphabetical ordering of facet buckets.
Solution
We implemented automatic UUID resolution for all facet types using the existing ObjectCacheService.getMultipleObjectNames() method, which provides efficient batch loading and multi-tier caching.
Changes Made
- Updated GuzzleSolrService Constructor - Added
ObjectCacheServiceas a dependency - Enhanced formatTermsFacetData Method - Modified to detect UUIDs, batch resolve them, and sort alphabetically by resolved names
How It Works
- UUID Detection: Checks if facet values contain hyphens (simple but effective UUID detection)
- Batch Resolution: Uses
ObjectCacheService.getMultipleObjectNames()for efficient batch retrieval - Cache Hierarchy: Checks in-memory cache → distributed cache → database
- Name Extraction: Searches common name fields (naam, name, title, contractNummer, achternaam)
- Alphabetical Sorting: Sorts by resolved labels (case-insensitive A-Z)
Example Result
Before UUID Resolution:
{
"customer": {
"buckets": [
{ "value": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "count": 42, "label": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }
]
}
}
After UUID Resolution:
{
"customer": {
"buckets": [
{ "value": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "count": 42, "label": "Acme Corporation" }
]
}
}
Performance Impact
- UUID detection: Simple string check - negligible cost
- Batch loading: Single query for all UUIDs instead of N queries
- Cache hits: Most UUIDs resolved from cache without database access
- Lazy evaluation: Only processes values that look like UUIDs
SOLR Field Dialog - Collection Support
Issue
The "SOLR Field Configuration" dialog only showed missing fields for the Object Collection, not the File Collection.
Solution
Updated the backend to query both collections and return fields with collection identifiers.
Changes Made
- Updated
SettingsController::getSolrFields()- Now calls bothgetObjectCollectionFieldStatus()andgetFileCollectionFieldStatus() - Fixed
SolrSchemaServiceCollection Query Methods - Properly queries both object and file collections - Added Collection Properties - Each field now includes
collectionandcollectionLabelproperties
New Response Format
{
"success": true,
"comparison": {
"total_differences": 194,
"missing_count": 131,
"extra_count": 63,
"missing": [
{
"name": "file_id",
"type": "plong",
"collection": "files",
"collectionLabel": "File Collection"
},
{
"name": "self_tenant",
"type": "string",
"collection": "objects",
"collectionLabel": "Object Collection"
}
],
"object_collection": {
"missing": 131,
"extra": 50
},
"file_collection": {
"missing": 63,
"extra": 13
}
}
}
Benefits
- ✅ Complete visibility - See all missing fields across all collections
- ✅ Better organization - Fields grouped by collection
- ✅ Actionable insights - Know exactly which collection needs which fields
- ✅ Consistent schema - Ensure both collections have required fields
Date: 2025-10-13
SOLR Service Refactoring Status
Current Status
Phase 1 In Progress - Basic functionality verified
Verified Working
- SOLR connection: Connected
- Total Objects indexed: 57,310
- Published Objects: 36,750
- Dashboard stats API: Working correctly
- Object search: Functional
- Collection separation:
objectCollectionandfileCollectionconfigured
Completed
- Created
SolrObjectService- Object-specific operations wrapper - Created
SolrFileService- File-specific operations wrapper with placeholder implementations - Updated
getDashboardStats()to query both collections separately - Created comprehensive architecture documentation
Service Architecture
Current State (Phase 1):
┌─────────────────────────────────────┐
│ ObjectService │
│ (High-level orchestration) │
└─────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ GuzzleSolrService │
│ (Currently handles EVERYTHING) │
│ • Core SOLR operations │
│ • Object indexing │
│ • File operations │
│ • Search │
└─────────────────────────────────────┘
Target State (Phase 1 Complete):
┌─────────────────────────────────────┐
│ ObjectService │
│ (High-level orchestration) │
└───┬───────────────┬─────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│SolrObjectSvc │ │ SolrFileSvc │
│(Objects) │ │ (Files) │
└───┬──────────┘ └─────┬────────────┘
│ │
└───────┬───────────┘
▼
┌───────────────────────┐
│ GuzzleSolrService │
│ (Core only) │
│ • Connection mgmt │
│ • Collections │
│ • HTTP client │
│ • Admin operations │
└───────────────────────┘
Refactoring Strategy
Phase 1A: Service Wrappers (✅ DONE)
- Create
SolrObjectServicewith delegation methods - Create
SolrFileServicewith placeholder methods - Add
getObjectCollection()andgetFileCollection()helpers - Update dashboard stats to query both collections
Phase 1B: Gradual Migration (NEXT)
Instead of moving code immediately:
- ✅ Keep
GuzzleSolrServicemethods working as-is - ✅ Have new services delegate to existing methods
- ✅ Update
ObjectServiceto useSolrObjectServiceinstead - ⏳ Later phases will move actual implementation
This ensures zero downtime and continuous functionality.
Collections Configuration
{
"objectCollection": "nc_test_local_objects", // For objects
"fileCollection": "nc_test_local_files", // For files (future)
"collection": "legacy_collection" // Deprecated, will be removed
}
Risk Assessment
Low Risk ✅
- Current approach (wrapper services)
- Dashboard stats changes
- Adding new services without removing old code
Medium Risk ⚠️
- Updating ObjectService injection
- Removing legacy
collectionfield
High Risk ❌
- Moving indexing logic between services (deferred to later phase)
- Changing database queries
- Modifying search algorithms
Rollback Plan
If issues occur:
- Revert
ObjectServiceto useGuzzleSolrServicedirectly - Keep dashboard stats changes (they're backward compatible)
- New services (
SolrObjectService,SolrFileService) can remain as they delegate to existing methods - No database changes have been made yet
Date: October 13, 2025
Related Documentation
- Solr Setup and Configuration - Complete Solr setup guide
- Solr Dashboard Management - Dashboard management documentation
- Faceting System - Faceting documentation with UUID resolution details