Filter by nested elements from search field?

If I have a list of music Albums that have a nested list of songs, is it possible to search with a combination of “Album name Song name” in the search field? If I add song.title to the searchable fields it does indeed search correctly, but I would like to display the song itself rather than the album.

I would like to be able to search “Song Name” and show a hit result of “Song Name - 3:32 - 1996”. Currently the result is the Album object.

The obvious answer would be to break out each song into individual Algolia objects. If I do that however I will quickly be in the $900 / month price tag for a hobby app. And the actual song object is extremely simple, just the title and track length. Seems overkill to make an entire object for that.

Hi there!

Unfortunately you can not retrieve a partial object from a nested attribute. The solution would be to have a different index with this new object, as you mentioned.

I agree that if your nested object is rather small, it’s ok to keep it simple and keep it in the main object.

I think you can implement the logic of retrieving “songs” manually. Something like “if the result matches a song title, instantiate a Song with it’s attributes.”. Then you choose you to display “Albums” and “Songs” differently according to this.

I have been tinkering with that idea, but using React InstantSearch is a bit of a black box. How can I tell if the search match is coming from different keys, like the Album name or the Song name? How can I get that key/value without iterating over the entire album object hit result?

If each song has an id as the key, I need to retrieve it so the user could click on it and add it to a “favorites” in my backend.

Hey, can you write with some code what you actually find complicated? You should be able to use the <Hits hitComponent={Hit} /> with Hit being any React component, it gets an object with all the attributes on that record (you can use . to go to nested keys like in any JS). You can then use _highlightResult to figure out which one actually matched.

const MatchingArray = ({ values }) =>
  values
    .filter(({ matchLevel }) => matchLevel === 'full')
    .map(value => <pre>{JSON.stringify(value)}</pre>);

const Hit = ({
  hit: { _highlightResult, title, actors },
}) =>
  // if there's a match in the title, show it, otherwise show the actors
  _highlightResult.title.matchLevel === 'full' ? (
    <pre>{JSON.stringify(_highlightResult.title)}</pre>
  ) : (
    // sometimes it's a single object instead of an array
    <MatchingArray values={[..._highlightResult.actors]} />
  );

see https://codesandbox.io/s/7mj202xoqj for the index I tried this with

Obviously it still makes more sense to do it in multiple objects, but I get your point for not wanting to do it because of price (800k objects does sound like a lot)

Unfortunately yes, this is a great case where the previous pricing model would have worked much better I believe. My dashboard says I can still get the previous pricing since I signed up before the switch, but I don’t remember the exact details of the pricing. Is it still published anywhere?

the old pricing is available on web archive: https://web.archive.org/web/20170601014932/algolia.com/pricing