acupofjose / elasticstore

A pluggable union between Firebase CloudFirestore + ElasticSearch
MIT License
130 stars 22 forks source link

TypeError: Cannot read property 'onSnapshot' of undefined #42

Closed valentin-harrang closed 3 years ago

valentin-harrang commented 3 years ago

Hi,

I followed your tutorial on Medium (https://medium.com/@acupofjose/wondering-how-to-get-elasticsearch-and-firebases-firestore-to-play-nice-1d84553aa280) and I'm stuck at the last step.

I have an events collection on Firestore and a location subcollection which has a geopoint type field which is called geopoints like this:

Untitled Project

I added this lines in references.ts file without error during the npm start command:

import { Reference } from "./types"

// Records should be added here to be indexed / made searchable
const references: Array<Reference> = [
  {
    collection: "events",
    subcollection: "location",
    index: "event-location",
    mappings: {
        geopoints: {
          // Elasticsearch's 'geo_point' needs to be specified
          type: "geo_point"
      }
    },
    // Transform data as we receive it from firestore
    transform: (data, parent) => ({
      ...data,
     location:`${data.location.geopoints_latitude},${data.location.geopoints._longitude}`
    })
  },
]

export default references

And this is my function in my React project:

import firebase from '@config/firebase';

export const getEvents = () => {
  const result = firebase.firestore().collection('search').add({
    request: {
      index: 'events',
      type: 'events',
      body: {},
    },
    response: null
  })

  result.ref.onSnapshot(doc => {
    if (doc.response !== null) {
      console.log(doc.response)
    }
  })
};

I get this error after calling getEvents function:

TypeError: Cannot read property 'onSnapshot' of undefined

My goal is to reduce the number of requests to Firestore by retrieving all my events stored in Firestore first and then retrieving my events which have a latitude and longitude of X kilometers radius from a latitude and longitude of a user. So, for now I would like to test if it's functional and I don't need to create a query in body.

Do you know where this error can come from? Moreover, I do not understand what the type key is for, can you explain me please?

Thank you in advance :)

acupofjose commented 3 years ago

@ElGecko76 I believe you're missing an await:

const result = **await** firebase.firestore().collection('search').add({
    request: {
      index: 'events',
      type: 'events',
      body: {},
    },
    response: null
  })

The type key is depreciated now - I should update the README to reflect that - sorry!

Hope that helps!

valentin-harrang commented 3 years ago

@acupofjose Wow thank you for this express response!

Okay thank you for this information, I removed the type key.

I already tried to add await but same error

I get this in console when I execute my function:

image

Does this mean that it works and that it is only on the application side that I cannot display the answer?

acupofjose commented 3 years ago

Yessir!

I'm actually a little lost on that code block - I'm unfamiliar with an import for @config/firebase. If you're getting an undefined `` that seems to be

Would it not be:


import firebase from '@firebase/app';
import '@firebase/firestore'

export const getEvents = async () => {
  const ref = await firebase.firestore().collection('search')

  ref.onSnapshot(doc => {
    if (doc.response !== null) {
      console.log(doc.response)
    }
  })

  await ref.add({
    request: {
      index: 'events',
      body: {},
    },
    response: null
  })
}
acupofjose commented 3 years ago

You should be seeing search documents added to the firebase console. Then it's just a matter of displaying them!

valentin-harrang commented 3 years ago

@acupofjose Thank you! But I get undefined in console.log(doc.response);

Yep I see this:

image

It is not very useful besides x)

acupofjose commented 3 years ago

Ha - yes you'll need to put a query in to actually get some results, try

{
  "request": {
    "index": "events",
    "q": "*"
  },
  "response": null
}
valentin-harrang commented 3 years ago

Still undefined and there is written:

ResponseError: index_not_found_exception

import firebase from '@firebase/app';
import '@firebase/firestore'

export const getEvents = async () => {
  const ref = await firebase.firestore().collection('search')

  ref.onSnapshot(doc => {
    if (doc.response !== null) {
      console.log(doc.response)
    }
  })

  await ref.add({
    request: {
      index: 'events',
      q: '*',
    },
    response: null
  })
}

image

acupofjose commented 3 years ago

Whoops, I didn't see how you defined the references.ts you'll have to use event-location as your index

valentin-harrang commented 3 years ago

@acupofjose There is exactly the same problem but with this index :/

acupofjose commented 3 years ago

Cool - I'd check with Kibana then and make sure that elasticstore is actually showing your documents.

My guess is that it will not be showing anything in it. In which case, you should remove the subcollection: 'location' from your references.ts file. (You aren't actually looking for a subcollection on that document, just a map).

After updating your references, restart elasticstore and make sure that the terminal window shows that it has processed a document.

valentin-harrang commented 3 years ago

@acupofjose thank you, it's better:

image

On the other hand, it is the entire document that is stored

acupofjose commented 3 years ago

You can fix that using the the options available for references.ts as listed in the readme. Either using include, exclude or transform.

For instance, using how you already have it set up, you can just mirror the location.geopoints to location key like this:

transform: (data, parent) => ({
  location:`${data.location.geopoints_latitude},${data.location.geopoints._longitude}`
})
valentin-harrang commented 3 years ago

@acupofjose Thank you very much!! :smile:

acupofjose commented 3 years ago

Yep! Happy to.