public void performWork(LuceneWork work, IndexWriter writer) {
    final Class<?> entityType = work.getEntityClass();
    final Serializable id = work.getId();
    log.tracef("Removing %s#%s by query.", entityType, id);
    DocumentBuilderIndexedEntity<?> builder = workspace.getDocumentBuilder(entityType);

    BooleanQuery entityDeletionQuery = new BooleanQuery();

    Query idQueryTerm;
    if (isIdNumeric(builder)) {
      idQueryTerm = NumericFieldUtils.createExactMatchQuery(builder.getIdKeywordName(), id);
    } else {
      idQueryTerm = new TermQuery(builder.getTerm(id));
    }
    entityDeletionQuery.add(idQueryTerm, BooleanClause.Occur.MUST);

    Term classNameQueryTerm = new Term(ProjectionConstants.OBJECT_CLASS, entityType.getName());
    TermQuery classNameQuery = new TermQuery(classNameQueryTerm);
    entityDeletionQuery.add(classNameQuery, BooleanClause.Occur.MUST);

    try {
      writer.deleteDocuments(entityDeletionQuery);
    } catch (Exception e) {
      String message = "Unable to remove " + entityType + "#" + id + " from index.";
      throw new SearchException(message, e);
    }
  }
 @Override
 public final void performOperation(
     LuceneWork work,
     IndexShardingStrategy shardingStrategy,
     WorkQueuePerIndexSplitter context) {
   IndexManager indexManager =
       shardingStrategy.getIndexManagerForAddition(
           work.getEntityClass(), work.getId(), work.getIdInString(), work.getDocument());
   context.getIndexManagerQueue(indexManager).add(work);
 }
 @Override
 public final void performOperation(
     LuceneWork work,
     IndexShardingStrategy shardingStrategy,
     WorkQueuePerIndexSplitter context) {
   IndexManager[] indexManagers =
       shardingStrategy.getIndexManagersForDeletion(
           work.getEntityClass(), work.getId(), work.getIdInString());
   for (IndexManager indexManager : indexManagers) {
     context.getIndexManagerQueue(indexManager).add(work);
   }
 }
 private void sendWorkToShards(LuceneWork work, boolean forceAsync) {
   final Class<?> entityType = work.getEntityClass();
   EntityIndexBinding entityIndexBinding = searchFactoryImplementor.getIndexBinding(entityType);
   IndexShardingStrategy shardingStrategy = entityIndexBinding.getSelectionStrategy();
   if (forceAsync) {
     work.getWorkDelegate(StreamingSelectionVisitor.INSTANCE)
         .performStreamOperation(work, shardingStrategy, progressMonitor, forceAsync);
   } else {
     WorkQueuePerIndexSplitter workContext = new WorkQueuePerIndexSplitter();
     work.getWorkDelegate(TransactionalSelectionVisitor.INSTANCE)
         .performOperation(work, shardingStrategy, workContext);
     workContext.commitOperations(
         progressMonitor); // FIXME I need a "Force sync" actually for when using PurgeAll before
                           // the indexing starts
   }
 }
 @Override
 public void performWork(LuceneWork work, IndexWriterDelegate delegate, IndexingMonitor monitor) {
   final Serializable id = work.getId();
   final String tenantId = work.getTenantId();
   final Class<?> managedType = work.getEntityClass();
   DocumentBuilderIndexedEntity builder = workspace.getDocumentBuilder(managedType);
   try {
     if (DeleteWorkExecutor.isIdNumeric(builder)) {
       log.tracef(
           "Deleting %s#%s by query using an IndexWriter#updateDocument as id is Numeric",
           managedType, id);
       Query exactMatchQuery =
           NumericFieldUtils.createExactMatchQuery(builder.getIdKeywordName(), id);
       BooleanQuery.Builder deleteDocumentsQueryBuilder = new BooleanQuery.Builder();
       deleteDocumentsQueryBuilder.add(exactMatchQuery, Occur.FILTER);
       if (tenantId != null) {
         TermQuery tenantTermQuery =
             new TermQuery(new Term(DocumentBuilderIndexedEntity.TENANT_ID_FIELDNAME, tenantId));
         deleteDocumentsQueryBuilder.add(tenantTermQuery, Occur.FILTER);
       }
       delegate.deleteDocuments(deleteDocumentsQueryBuilder.build());
       // no need to log the Add operation as we'll log in the delegate
       this.addDelegate.performWork(work, delegate, monitor);
     } else {
       log.tracef("Updating %s#%s by id using an IndexWriter#updateDocument.", managedType, id);
       Term idTerm = new Term(builder.getIdKeywordName(), work.getIdInString());
       Map<String, String> fieldToAnalyzerMap = work.getFieldToAnalyzerMap();
       ScopedAnalyzerReference analyzerReference = builder.getAnalyzerReference();
       analyzerReference =
           AddWorkExecutor.updateAnalyzerMappings(
               workspace, analyzerReference, fieldToAnalyzerMap);
       delegate.updateDocument(idTerm, work.getDocument(), analyzerReference);
     }
     workspace.notifyWorkApplied(work);
   } catch (Exception e) {
     String message = "Unable to update " + managedType + "#" + id + " in index.";
     throw new SearchException(message, e);
   }
   if (monitor != null) {
     monitor.documentsAdded(1l);
   }
 }