diff --git a/src/app/child-dev-project/attendance/model/recurring-activity.spec.ts b/src/app/child-dev-project/attendance/model/recurring-activity.spec.ts
index e6299353dd..3b17b2aa88 100644
--- a/src/app/child-dev-project/attendance/model/recurring-activity.spec.ts
+++ b/src/app/child-dev-project/attendance/model/recurring-activity.spec.ts
@@ -29,7 +29,5 @@ describe("RecurringActivity", () => {
     participants: ["1", "2"],
     linkedGroups: ["3"],
     excludedParticipants: ["5"],
-
-    searchIndices: ["test", "activity"],
   });
 });
diff --git a/src/app/child-dev-project/children/model/child.spec.ts b/src/app/child-dev-project/children/model/child.spec.ts
index b7dc8237ec..ab4f350743 100644
--- a/src/app/child-dev-project/children/model/child.spec.ts
+++ b/src/app/child-dev-project/children/model/child.spec.ts
@@ -37,8 +37,6 @@ describe("Child", () => {
     dropoutDate: new Date("2022-03-31"),
     dropoutType: "unknown",
     dropoutRemarks: "no idea what happened",
-
-    searchIndices: ["Max", "projectNumber01"],
   });
 
   it("should determine isActive based on inferred state", () => {
diff --git a/src/app/child-dev-project/children/model/child.ts b/src/app/child-dev-project/children/model/child.ts
index 252752e61e..1f995fe6ad 100644
--- a/src/app/child-dev-project/children/model/child.ts
+++ b/src/app/child-dev-project/children/model/child.ts
@@ -57,6 +57,7 @@ export class Child extends Entity {
   @DatabaseField({
     label: $localize`:Label for the project number of a child:Project Number`,
     labelShort: $localize`:Short label for the project number:PN`,
+    searchable: true,
   })
   projectNumber: string;
 
@@ -135,19 +136,4 @@ export class Child extends Entity {
       super.isActive
     );
   }
-
-  /**
-   * @override see {@link Entity}
-   */
-  @DatabaseField() get searchIndices(): string[] {
-    let indices = [];
-
-    indices = indices.concat(this.toString().split(" "));
-    if (this.projectNumber !== undefined && this.projectNumber !== null) {
-      indices.push(this.projectNumber);
-    }
-    return indices;
-  }
-
-  set searchIndices(value) {}
 }
diff --git a/src/app/child-dev-project/schools/model/school.spec.ts b/src/app/child-dev-project/schools/model/school.spec.ts
index 8625220fae..16a0d5eee4 100644
--- a/src/app/child-dev-project/schools/model/school.spec.ts
+++ b/src/app/child-dev-project/schools/model/school.spec.ts
@@ -22,6 +22,5 @@ describe("School Entity", () => {
   testEntitySubclass("School", School, {
     _id: "School:some-id",
     name: "Max",
-    searchIndices: ["Max"],
   });
 });
diff --git a/src/app/core/entity/model/entity.spec.ts b/src/app/core/entity/model/entity.spec.ts
index 111e5bff2a..0b5b499dd6 100644
--- a/src/app/core/entity/model/entity.spec.ts
+++ b/src/app/core/entity/model/entity.spec.ts
@@ -51,29 +51,6 @@ describe("Entity", () => {
     expect(data.otherText).toBeUndefined();
   });
 
-  it("rawData() includes searchIndices containing toString parts", function () {
-    const id = "test1";
-    const entity = new Entity(id);
-    entity.toString = () => entity["name"];
-    entity["name"] = "John Doe";
-
-    const data = entitySchemaService.transformEntityToDatabaseFormat(entity);
-
-    expect(data.searchIndices).toBeDefined();
-    expect(data.searchIndices).toContain("John");
-    expect(data.searchIndices).toContain("Doe");
-  });
-
-  it("should not generate searchIndices for entities without a custom toString method", function () {
-    const id = "test1";
-    const entity = new Entity(id);
-    entity["name"] = "John Doe";
-
-    const data = entitySchemaService.transformEntityToDatabaseFormat(entity);
-
-    expect(data.searchIndices).toEqual([]);
-  });
-
   it("can perform a shallow copy of itself", () => {
     const id = "t1";
     const entity: Entity = new Entity(id);
@@ -176,9 +153,6 @@ export function testEntitySubclass(
       JSON.parse(JSON.stringify(expectedDatabaseFormat))
     );
     const rawData = schemaService.transformEntityToDatabaseFormat(entity);
-    if (rawData.searchIndices.length === 0) {
-      delete rawData.searchIndices;
-    }
     expect(rawData).toEqual(expectedDatabaseFormat);
   }));
 }
diff --git a/src/app/core/entity/model/entity.ts b/src/app/core/entity/model/entity.ts
index 54c7aa1aa2..fd4c301f0b 100644
--- a/src/app/core/entity/model/entity.ts
+++ b/src/app/core/entity/model/entity.ts
@@ -194,31 +194,6 @@ export class Entity {
     this._id = Entity.createPrefixedId(this.getType(), newEntityId);
   }
 
-  /**
-   * Returns an array of strings by which the entity can be searched.
-   *
-   * By default the parts of the string representation (toString) split at spaces is used if it is present.
-   *
-   * <b>Overwrite this method in subtypes if you want an entity type to be searchable by other properties.</b>
-   */
-  @DatabaseField() get searchIndices(): string[] {
-    if (
-      this.getConstructor().toStringAttributes === Entity.toStringAttributes &&
-      this.toString() === this.entityId
-    ) {
-      // no indices for the default if an entity does not have a human-readable name
-      return [];
-    }
-
-    // default indices generated from toString
-    return this.toString().split(" ");
-  }
-
-  set searchIndices(value) {
-    // do nothing, always generated on the fly
-    // searchIndices is only saved to database so it can be used internally for database indexing
-  }
-
   /**
    * Check, if this entity is considered active.
    * This is either taken from the property "inactive" (configured) or "active" (not configured).
diff --git a/src/app/core/entity/schema/entity-schema-field.ts b/src/app/core/entity/schema/entity-schema-field.ts
index a20db589e9..8d89dd72a1 100644
--- a/src/app/core/entity/schema/entity-schema-field.ts
+++ b/src/app/core/entity/schema/entity-schema-field.ts
@@ -47,6 +47,11 @@ export interface EntitySchemaField {
    */
   generateIndex?: boolean; // TODO: implement index support in EntitySchema
 
+  /**
+   * If set to `true`, the entity can be found in the global search by entering this value
+   */
+  searchable?: boolean;
+
   /**
    * Whether the field should be initialized with a default value if undefined
    * (which is then run through dataType transformation);
diff --git a/src/app/core/ui/search/search.component.spec.ts b/src/app/core/ui/search/search.component.spec.ts
index 86dc05f18c..3676cec17f 100644
--- a/src/app/core/ui/search/search.component.spec.ts
+++ b/src/app/core/ui/search/search.component.spec.ts
@@ -7,14 +7,10 @@ import {
 } from "@angular/core/testing";
 
 import { SearchComponent } from "./search.component";
-import { Child } from "../../../child-dev-project/children/model/child";
-import { School } from "../../../child-dev-project/schools/model/school";
 import { DatabaseIndexingService } from "../../entity/database-indexing/database-indexing.service";
 import { Subscription } from "rxjs";
-import { Entity } from "../../entity/model/entity";
 import { MockedTestingModule } from "../../../utils/mocked-testing.module";
 import { SwUpdate } from "@angular/service-worker";
-import { UserRoleGuard } from "../../permissions/permission-guard/user-role.guard";
 
 describe("SearchComponent", () => {
   SearchComponent.INPUT_DEBOUNCE_TIME_MS = 4;
@@ -36,7 +32,6 @@ describe("SearchComponent", () => {
     TestBed.configureTestingModule({
       imports: [SearchComponent, MockedTestingModule.withState()],
       providers: [
-        UserRoleGuard,
         { provide: DatabaseIndexingService, useValue: mockIndexService },
         { provide: SwUpdate, useValue: {} },
       ],
@@ -69,11 +64,6 @@ describe("SearchComponent", () => {
 
     component.formControl.setValue("AB");
     tick(SearchComponent.INPUT_DEBOUNCE_TIME_MS * 2);
-    expect(component.state).toBe(component.TOO_FEW_CHARACTERS);
-    expect(mockIndexService.queryIndexRaw).not.toHaveBeenCalled();
-
-    component.formControl.setValue("ABC");
-    tick(SearchComponent.INPUT_DEBOUNCE_TIME_MS * 2);
     expect(component.state).toBe(component.NO_RESULTS);
     expect(mockIndexService.queryIndexRaw).toHaveBeenCalled();
 
@@ -97,58 +87,4 @@ describe("SearchComponent", () => {
     expectResultToBeEmpty(done);
     component.formControl.setValue(null);
   });
-
-  function expectResultToHave(queryResults: any, result: Entity, done: DoneFn) {
-    mockIndexService.queryIndexRaw.and.returnValue(
-      Promise.resolve(queryResults)
-    );
-
-    subscription = component.results.subscribe((next) => {
-      expect(next).toHaveSize(1);
-      expect(next[0]).toHaveId(result.getId());
-      expect(mockIndexService.queryIndexRaw).toHaveBeenCalled();
-      done();
-    });
-  }
-
-  function generateDemoData(): [Child, School, object] {
-    const child1 = new Child("1");
-    child1.name = "Adam X";
-    const school1 = new School("s1");
-    school1.name = "Anglo Primary";
-    const mockQueryResults = {
-      rows: [
-        { id: child1.getId(true), doc: { name: child1.name }, key: "adam" },
-        { id: child1.getId(true), doc: { name: child1.name }, key: "x" },
-        { id: school1.getId(true), doc: { name: school1.name }, key: "anglo" },
-        {
-          id: school1.getId(true),
-          doc: { name: school1.name },
-          key: "primary",
-        },
-      ],
-    };
-    return [child1, school1, mockQueryResults];
-  }
-
-  it("should set results correctly for search input", (done) => {
-    const [child1, , mockQueryResults] = generateDemoData();
-
-    expectResultToHave(mockQueryResults, child1, done);
-    component.formControl.setValue("Ada");
-  });
-
-  it("should not include duplicates in results", (done) => {
-    const [child1, , mockQueryResults] = generateDemoData();
-
-    expectResultToHave(mockQueryResults, child1, done);
-    component.formControl.setValue("Ada");
-  });
-
-  it("should only include results matching all search terms (words)", (done) => {
-    const [child1, , mockQueryResults] = generateDemoData();
-
-    expectResultToHave(mockQueryResults, child1, done);
-    component.formControl.setValue("A X");
-  });
 });
diff --git a/src/app/core/ui/search/search.component.ts b/src/app/core/ui/search/search.component.ts
index 4d752f5404..d3a500ec20 100644
--- a/src/app/core/ui/search/search.component.ts
+++ b/src/app/core/ui/search/search.component.ts
@@ -1,12 +1,9 @@
 import { Component, ViewEncapsulation } from "@angular/core";
 import { Entity } from "../../entity/model/entity";
-import { from, Observable } from "rxjs";
-import { concatMap, debounceTime, skipUntil, tap } from "rxjs/operators";
-import { DatabaseIndexingService } from "../../entity/database-indexing/database-indexing.service";
+import { Observable } from "rxjs";
+import { concatMap, debounceTime, tap } from "rxjs/operators";
 import { Router } from "@angular/router";
 import { FormControl, ReactiveFormsModule } from "@angular/forms";
-import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
-import { EntityRegistry } from "../../entity/database-entity.decorator";
 import { UserRoleGuard } from "../../permissions/permission-guard/user-role.guard";
 import { MatFormFieldModule } from "@angular/material/form-field";
 import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
@@ -15,6 +12,7 @@ import { MatAutocompleteModule } from "@angular/material/autocomplete";
 import { AsyncPipe, NgForOf, NgSwitch, NgSwitchCase } from "@angular/common";
 import { DisplayEntityComponent } from "../../entity-components/entity-select/display-entity/display-entity.component";
 import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
+import { SearchService } from "./search.service";
 
 /**
  * General search box that provides results out of any kind of entities from the system
@@ -43,8 +41,8 @@ import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
   standalone: true,
 })
 export class SearchComponent {
-  static INPUT_DEBOUNCE_TIME_MS: number = 400;
-  MIN_CHARACTERS_FOR_SEARCH: number = 3;
+  static INPUT_DEBOUNCE_TIME_MS = 400;
+  MIN_CHARACTERS_FOR_SEARCH = 2;
 
   readonly NOTHING_ENTERED = 0;
   readonly TOO_FEW_CHARACTERS = 1;
@@ -60,15 +58,12 @@ export class SearchComponent {
   results: Observable<Entity[]>;
 
   constructor(
-    private indexingService: DatabaseIndexingService,
     private router: Router,
     private userRoleGuard: UserRoleGuard,
-    private entitySchemaService: EntitySchemaService,
-    private entities: EntityRegistry
+    private searchService: SearchService
   ) {
     this.results = this.formControl.valueChanges.pipe(
       debounceTime(SearchComponent.INPUT_DEBOUNCE_TIME_MS),
-      skipUntil(this.createSearchIndex()),
       tap((next) => (this.state = this.updateState(next))),
       concatMap((next: string) => this.searchResults(next)),
       untilDestroyed(this)
@@ -94,19 +89,10 @@ export class SearchComponent {
     if (this.state !== this.SEARCH_IN_PROGRESS) {
       return [];
     }
-    const searchTerms = next.toLowerCase().split(" ");
-    const entities = await this.indexingService.queryIndexRaw(
-      "search_index/by_name",
-      {
-        startkey: searchTerms[0],
-        endkey: searchTerms[0] + "\ufff0",
-        include_docs: true,
-      }
-    );
-    const filtered = this.prepareResults(entities.rows, searchTerms);
-    const uniques = this.uniquify(filtered);
-    this.state = uniques.length === 0 ? this.NO_RESULTS : this.SHOW_RESULTS;
-    return uniques;
+    const entities = await this.searchService.getSearchResults(next);
+    const filtered = this.prepareResults(entities);
+    this.state = filtered.length === 0 ? this.NO_RESULTS : this.SHOW_RESULTS;
+    return filtered;
   }
 
   async clickOption(optionElement) {
@@ -126,68 +112,9 @@ export class SearchComponent {
     return /^[a-zA-Z]+|\d+$/.test(searchText);
   }
 
-  private createSearchIndex(): Observable<void> {
-    // `emit(x)` to add x as a key to the index that can be searched
-    const searchMapFunction = `
-      (doc) => {
-        if (doc.hasOwnProperty("searchIndices")) {
-           doc.searchIndices.forEach(word => emit(word.toString().toLowerCase()));
-        }
-      }`;
-
-    const designDoc = {
-      _id: "_design/search_index",
-      views: {
-        by_name: {
-          map: searchMapFunction,
-        },
-      },
-    };
-
-    // TODO move this to a service so it is not executed whenever a user logs in
-    return from(this.indexingService.createIndex(designDoc));
-  }
-
-  private prepareResults(
-    rows: [{ key: string; id: string; doc: object }],
-    searchTerms: string[]
-  ): Entity[] {
-    return rows
-      .map((doc) => this.transformDocToEntity(doc))
-      .filter((entity) =>
-        this.userRoleGuard.checkRoutePermissions(entity.getConstructor().route)
-      )
-      .filter((entity) =>
-        this.containsSecondarySearchTerms(entity, searchTerms)
-      );
-  }
-
-  private containsSecondarySearchTerms(
-    entity: Entity,
-    searchTerms: string[]
-  ): boolean {
-    const searchIndices = entity.searchIndices.join(" ").toLowerCase();
-    return searchTerms.every((s) => searchIndices.includes(s));
-  }
-
-  private uniquify(entities: Entity[]): Entity[] {
-    const uniques = new Map<string, Entity>();
-    entities.forEach((e) => {
-      uniques.set(e.getId(), e);
-    });
-    return [...uniques.values()];
-  }
-
-  private transformDocToEntity(doc: {
-    key: string;
-    id: string;
-    doc: object;
-  }): Entity {
-    const ctor = this.entities.get(Entity.extractTypeFromId(doc.id));
-    const entity = doc.id ? new ctor(doc.id) : new ctor();
-    if (doc.doc) {
-      this.entitySchemaService.loadDataIntoEntity(entity, doc.doc);
-    }
-    return entity;
+  private prepareResults(entities: Entity[]): Entity[] {
+    return entities.filter((entity) =>
+      this.userRoleGuard.checkRoutePermissions(entity.getConstructor().route)
+    );
   }
 }
diff --git a/src/app/core/ui/search/search.service.spec.ts b/src/app/core/ui/search/search.service.spec.ts
new file mode 100644
index 0000000000..a41dc1f81a
--- /dev/null
+++ b/src/app/core/ui/search/search.service.spec.ts
@@ -0,0 +1,112 @@
+import { TestBed } from "@angular/core/testing";
+
+import { SearchService } from "./search.service";
+import { DatabaseTestingModule } from "../../../utils/database-testing.module";
+import { ChildSchoolRelation } from "../../../child-dev-project/children/model/childSchoolRelation";
+import { Child } from "../../../child-dev-project/children/model/child";
+import { EntityMapperService } from "../../entity/entity-mapper.service";
+import { Database } from "../../database/database";
+
+describe("SearchService", () => {
+  let service: SearchService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({ imports: [DatabaseTestingModule] });
+  });
+
+  afterEach(() => TestBed.inject(Database).destroy());
+
+  it("should allow to search for toStringAttributes that are not the entityId", async () => {
+    ChildSchoolRelation.toStringAttributes = ["entityId"];
+    Child.toStringAttributes = ["name"];
+    const c1 = Child.create("first");
+    const c2 = Child.create("second");
+    const r = new ChildSchoolRelation("relation");
+    await TestBed.inject(EntityMapperService).saveAll([c1, c2, r]);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("firs");
+    expect(res).toEqual([c1]);
+    res = await service.getSearchResults("relation");
+    expect(res).toEqual([]);
+  });
+
+  it("should only index on database properties", async () => {
+    Child.toStringAttributes = ["schoolId", "name"];
+    const child = Child.create("test");
+    child.schoolId = "someSchool";
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("someSchool");
+    expect(res).toEqual([]);
+    res = await service.getSearchResults("test");
+    // reset default value
+    child.schoolId = "";
+    expect(res).toEqual([child]);
+  });
+
+  it("should not fail if toStringAttribute is not set", async () => {
+    Child.toStringAttributes = ["projectNumber", "name"];
+    const child = Child.create("test");
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    const res = await service.getSearchResults("test");
+    expect(res).toEqual([child]);
+  });
+
+  it("should include properties that are marked searchable", async () => {
+    Child.toStringAttributes = ["name"];
+    Child.schema.get("projectNumber").searchable = true;
+    const child = Child.create("test");
+    child.projectNumber = "number";
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("tes");
+    expect(res).toEqual([child]);
+    res = await service.getSearchResults("numb");
+    expect(res).toEqual([child]);
+
+    delete Child.schema.get("projectNumber").searchable;
+  });
+
+  it("should support search terms with multiple words", async () => {
+    Child.toStringAttributes = ["name", "projectNumber"];
+    const child = Child.create("test");
+    child.projectNumber = "number";
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("tes num");
+    expect(res).toEqual([child]);
+  });
+
+  it("should allows searches for properties with multiple words", async () => {
+    Child.toStringAttributes = ["name"];
+    const child = Child.create("test name");
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("nam");
+    expect(res).toEqual([child]);
+  });
+
+  it("should not return the same entity multiple times", async () => {
+    Child.toStringAttributes = ["name"];
+    const child = Child.create("Peter Petersilie");
+    await TestBed.inject(EntityMapperService).save(child);
+
+    service = TestBed.inject(SearchService);
+
+    let res = await service.getSearchResults("peter");
+    expect(res).toEqual([child]);
+  });
+});
diff --git a/src/app/core/ui/search/search.service.ts b/src/app/core/ui/search/search.service.ts
new file mode 100644
index 0000000000..97dd9c7ade
--- /dev/null
+++ b/src/app/core/ui/search/search.service.ts
@@ -0,0 +1,118 @@
+import { Injectable } from "@angular/core";
+import { DatabaseIndexingService } from "../../entity/database-indexing/database-indexing.service";
+import { Entity } from "../../entity/model/entity";
+import { EntityRegistry } from "../../entity/database-entity.decorator";
+import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
+
+/**
+ * This service handles to logic for global searches across all entities
+ */
+@Injectable({
+  providedIn: "root",
+})
+export class SearchService {
+  private searchableEntities: [string, string[]][];
+
+  constructor(
+    private indexingService: DatabaseIndexingService,
+    private schemaService: EntitySchemaService,
+    private entities: EntityRegistry
+  ) {
+    this.createSearchIndex();
+  }
+
+  /**
+   * Creates the search index based on the `toStringAttributes` and the `searchable` schema property
+   * @private
+   */
+  private createSearchIndex() {
+    this.initializeSearchableEntities();
+
+    const designDoc = {
+      _id: "_design/search_index",
+      views: {
+        by_name: {
+          map: this.getSearchIndexDesignDoc(),
+        },
+      },
+    };
+
+    this.indexingService.createIndex(designDoc);
+  }
+
+  private initializeSearchableEntities() {
+    this.searchableEntities = [...this.entities.entries()]
+      .map(([name, ctr]) => {
+        const stringAttributes = ctr.toStringAttributes.filter((attr) =>
+          ctr.schema.has(attr)
+        );
+        const searchableAttributes = [...ctr.schema.entries()]
+          .filter(([_, schema]) => schema.searchable)
+          .map(([name]) => name);
+        return [name, [...stringAttributes, ...searchableAttributes]] as [
+          string,
+          string[]
+        ];
+      })
+      .filter(([_, props]) => props.length > 0);
+  }
+
+  private getSearchIndexDesignDoc() {
+    let searchIndex = `(doc) => {\n`;
+    this.searchableEntities.forEach(([type, attributes]) => {
+      searchIndex += `if (doc._id.startsWith("${type}:")) {\n`;
+      attributes.forEach((attr) => {
+        searchIndex += `if (doc["${attr}"]) {\n`;
+        searchIndex += `doc["${attr}"].toString().toLowerCase().split(" ").forEach((val) => emit(val))\n`;
+        searchIndex += `}\n`;
+      });
+      searchIndex += `return\n`;
+      searchIndex += `}\n`;
+    });
+    searchIndex += `}`;
+    return searchIndex;
+  }
+
+  /**
+   * Returns the results matching the provided search term.
+   * Multiple search terms should be separated by a space
+   * @param searchTerm for which entities should be returned
+   */
+  async getSearchResults(searchTerm: string): Promise<Entity[]> {
+    const searchTerms = searchTerm.toLowerCase().split(" ");
+    const res = await this.indexingService.queryIndexRaw(
+      "search_index/by_name",
+      {
+        startkey: searchTerms[0],
+        endkey: searchTerms[0] + "\ufff0",
+        include_docs: true,
+      }
+    );
+    return this.getUniqueDocs(res.rows)
+      .filter((doc) => this.containsSecondarySearchTerms(doc, searchTerms))
+      .map((doc) => this.transformDocToEntity(doc));
+  }
+
+  private getUniqueDocs(rows: any[]): any[] {
+    const uniques = new Map<string, any>();
+    rows.forEach((row) => uniques.set(row.doc._id, row.doc));
+    return [...uniques.values()];
+  }
+
+  private containsSecondarySearchTerms(doc, searchTerms: string[]): boolean {
+    const entityType = Entity.extractTypeFromId(doc._id);
+    const values = this.searchableEntities
+      .find(([type]) => type === entityType)[1]
+      .map((attr) => doc[attr])
+      .join(" ")
+      .toLowerCase();
+    return searchTerms.every((s) => values.includes(s));
+  }
+
+  private transformDocToEntity(doc): Entity {
+    const ctor = this.entities.get(Entity.extractTypeFromId(doc._id));
+    const entity = new ctor(doc._id);
+    this.schemaService.loadDataIntoEntity(entity, doc);
+    return entity;
+  }
+}
diff --git a/src/app/core/user/user.spec.ts b/src/app/core/user/user.spec.ts
index d08b719c91..8752f8efc2 100644
--- a/src/app/core/user/user.spec.ts
+++ b/src/app/core/user/user.spec.ts
@@ -24,8 +24,6 @@ describe("User", () => {
 
     name: "tester",
     paginatorSettingsPageSize: {},
-
-    searchIndices: ["tester"],
   });
 
   it("should not allow to change the name after initialization and set it as the ID", () => {
diff --git a/src/app/features/data-import/data-import.service.spec.ts b/src/app/features/data-import/data-import.service.spec.ts
index 543f36d5e7..7b5a3d1b15 100644
--- a/src/app/features/data-import/data-import.service.spec.ts
+++ b/src/app/features/data-import/data-import.service.spec.ts
@@ -162,26 +162,6 @@ describe("DataImportService", () => {
     expect(test2.dateOfBirth).toBeDate("2011-06-07");
   });
 
-  it("should import csv file and generate searchIndices", async () => {
-    spyOn(db, "putAll");
-    const data = [{ name: "John Doe", projectNumber: "123" }];
-    const importMeta: ImportMetaData = {
-      entityType: "Child",
-      columnMap: {
-        name: { key: "name", label: "Name" },
-        projectNumber: { key: "projectNumber", label: "Project number" },
-      },
-    };
-
-    await service.handleCsvImport(data, importMeta);
-
-    expect(db.putAll).toHaveBeenCalledWith([
-      jasmine.objectContaining({
-        searchIndices: ["John", "Doe", "123"],
-      }),
-    ]);
-  });
-
   it("should save array strings as arrays", async () => {
     const data = [
       { ID: "1", children: '["one", "two"]' },
diff --git a/src/app/features/data-import/data-import.service.ts b/src/app/features/data-import/data-import.service.ts
index 1c982a771f..57a123996d 100644
--- a/src/app/features/data-import/data-import.service.ts
+++ b/src/app/features/data-import/data-import.service.ts
@@ -121,7 +121,6 @@ export class DataImportService {
   ): Promise<void> {
     const entities = data.map((row) => {
       const entity = this.createEntityWithRowData(row, importMeta);
-      this.createSearchIndices(importMeta, entity);
       if (!entity["_id"]) {
         entity["_id"] = `${importMeta.entityType}:${
           importMeta.transactionId
@@ -198,11 +197,6 @@ export class DataImportService {
     }
   }
 
-  private createSearchIndices(importMeta: ImportMetaData, entity) {
-    const ctor = this.entities.get(importMeta.entityType);
-    entity["searchIndices"] = Object.assign(new ctor(), entity).searchIndices;
-  }
-
   private linkEntities(entities: any[], importMeta: ImportMetaData) {
     return this.linkableEntities[importMeta.entityType].find(
       ([type]) => type.ENTITY_TYPE === importMeta.linkEntity.type
diff --git a/src/app/features/todos/model/todo.spec.ts b/src/app/features/todos/model/todo.spec.ts
index b09301725b..079a65c273 100644
--- a/src/app/features/todos/model/todo.spec.ts
+++ b/src/app/features/todos/model/todo.spec.ts
@@ -11,8 +11,6 @@ describe("Todo", () => {
     description: "details of the task",
     assignedTo: ["demo"],
     relatedEntities: [],
-
-    searchIndices: ["new", "task"],
   });
 
   it("should infer isOverdue", () => {
diff --git a/src/app/utils/expect-entity-data.spec.ts b/src/app/utils/expect-entity-data.spec.ts
index d2bd0abb33..cc6c9907c5 100644
--- a/src/app/utils/expect-entity-data.spec.ts
+++ b/src/app/utils/expect-entity-data.spec.ts
@@ -156,12 +156,10 @@ function comparableEntityData(obj: any | any[], withoutId: boolean = false) {
   if (Array.isArray(obj)) {
     return obj.map((o) => comparableEntityData(o, withoutId));
   } else {
-    const result = TestBed.inject(
-      EntitySchemaService
-    ).transformEntityToDatabaseFormat(obj);
+    const result =
+      TestBed.inject(EntitySchemaService).transformEntityToDatabaseFormat(obj);
 
     delete result._rev;
-    delete result.searchIndices;
     if (withoutId) {
       delete result._id;
     }