Create indexes programatically?

I have an app that has different users that will have different things to search, how can I create an index for a certain set of users so that another user1’s hits won’t show up in user2’s hit results. Is there a way I can do this where I don’t have to manually create an index with different users each time a user is created?

Hi @dantesauder ,

I suppose for the use-case you described it would be more convenient to use an implicit filtering within the same index.

Let’s imagine you have a two groups of users: group A and group B and just one index “MyIndex” containing all your records. You can add a field to your records, for example, called “group” with value “a” for the records you want to show to the group A of users, and the value “b” for the group B respectively. You can even add a list: "group": ["a", "b"], so the record will be available for both groups.
Then, you should set a query parameter filters: "group:a" or filters:"group:b" to get a result for a specific group.

You can read more about filtering in the documentation.

Is there like a code snippet you can send me or something sorry, I learn and understand better by seeing an example. I read through the documentation link and still have no idea where to put what and what to type where. How do I add fields to records, where do I add this list you mention and where do I set the query parameters at?

  struct Event: Encodable {
    
    let eventName: String
    let objectID: ObjectID
    let group: [String]


}

I’m assuming adding a field to a record would be like this. Now what would I do for saving the record in the object, I want the code to be dynamic, so I don’t know how I would implement the “group” concept you mentioned.

  @IBAction public func createEventButton(_ sender: UIButton) {

    let event: Event = .init(eventName: nameTextField.text!, objectID: ObjectID(rawValue: String(randomObjectID(digits: 8))), group: ["a"])

   let index = client.index(withName: "event_name")

    try index.saveObject(event) { result in
        if case .success(let response) = result {
            print("Response: \(response)")
        }
    }

What would I put for the group?

@dantesauder

Coming back to your initial message

how can I create an index for a certain set of users so that another user1’s hits won’t show up in user2’s hit results.

if you just want the answer to your initial question: there is no specific command to create an index, just send records to the name of the new index and it will be automatically created, as documented here: Manage Indices | API Reference | Algolia Documentation

This is best used in conjunction with the setSettings method as you usually want your indices to have a list of searchable attributes, a custom ranking, and other generic settings that would be suitable for the search experience.

However, what vladislav was suggesting was that this might not be the most appropriate solution depending on a few factors, which I list below:

  • How do you know that a certain record should only be seen by user1 rather than user2?
  • Do the records data only belong to one user or can multiple users see the same data?
  • How many users, how many records in total and per user do you expect?
  • Does the front-end directly connect to Algolia, or is everything proxied through a back-end service you control?
  • How sensitive is the data you are trying to hide from other users? Do you expect malicious behaviours, and how problematic would it be if a customer sees the data of another one (by actively seeking it)?

Based your answer to the first 3 questions, you can decide whether it is best for you to:

  • have one index per customer
  • have one index with all the data and a way to assign one record to one customer
  • have one index with all the data and a way to map a record to a group of customer that can see this record. Here the key concept is whether your users have traits that can be used as groups.

Based on your answer for the 4th and 5th question, you can define the security requirements for your application, which will apply constraints on how users can access the data and you should manage that access.

This will be helpful if you want to follow this guide on how to restrict access to the data that is available in our documentation:

I hope this helps!
Best,

I basically want to do the third option, have one index with all the data and map a record to a group of users, but I don’t get the last part. What do you mean by traits that can be used as groups? Like students under schools or something different?

Ok so I read through the docs a bit more and think I’ll just go with filtering, instead of trying to group records in an array. So I just set the settings and now I want to know if it’s possible to use logic for a search. For example I added schoolID as a parameter in my search. Is there a way I can use logic by getting the studentsID to see if it matches the schoolID, and if it does, show those searches?

@IBAction public func createEventButton(_ sender: UIButton) {

    let event: Event = .init(eventName: nameTextField.text!, objectID: ObjectID(rawValue: String(randomObjectID(digits: 8))), eventDate: dateTextField.text!, eventCost: costTextField.text!, forEventGrades: gradesTextField.text!, schoolID: schoolIDTextF.text!)

   let index = client.index(withName: "event_name")
    
    let settings = Settings()
    
        .set(\.searchableAttributes, to: [.default("eventName")])
        .set(\.attributesForFaceting, to: [.filterOnly("schoolID")])
        .set(\.attributesToRetrieve, to: ["eventName"])
    
    try index.setSettings(settings, completion: { (result) in
        if case .success(let response) = result {
            print("Success saving settings!")
        }
    })
    

    try index.saveObject(event) { result in
        if case .success(let response) = result {
            print("Response: \(response)")
        }
    }

This is what I setup before an event gets created and added to the index. I wanna know how I can filter out the searches with logic, to get the right results.

Hi @dantesauder ,

Once you saved a few events with an associated schoolID, you can search for them as follows:

let schoolID: String = "..."

let query = Query().set(\.filters, to: "schoolID:\(schoolID)")
index.search(query: query) { result in
  if case .success(let response) = result {
    print("Response: \(response)")
  }
}

Yeah I already tried that, plus I don’t wanna explicitly declare the schoolID as an empty String because when a record is added, the school ID is stored in the school ID textfield, and there’s going to be multiple users with different school ids, so i don’t want to manually change it everytime a search is made.

func updateSearchResults(for searchController: UISearchController) {
    let searchBar = searchController.searchBar
    let settings = Settings()

        .set(\.searchableAttributes, to: [.default("eventName")])
        .set(\.attributesForFaceting, to: [.filterOnly("schoolID")])
        .set(\.attributesToRetrieve, to: ["*"])

     index2.setSettings(settings) { (result) in
        if case .success(let response) = result {
            print("Response: \(response.wrapped)")
        }
    }
    getTheSchoolsID { (schoolID) in
        if let id = schoolID {
            let query = Query(searchBar.searchTextField.text!)

            
                .set(\.filters, to: "schoolID:\(id)")

            index2.search(query: query) { (result) in
                if case .success(let response) = result {
                    print("Query Success!")
                }
            }
        }
    }
}

This is what I got but it still doesn’t work, is there something wrong with the settings cause I genuinely don’t understand why it’s not working.