Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This is not working in the aggregation function #1

Open
ravikant-pal opened this issue Jun 27, 2024 · 0 comments
Open

This is not working in the aggregation function #1

ravikant-pal opened this issue Jun 27, 2024 · 0 comments

Comments

@ravikant-pal
Copy link

I have this schema

const AddressSchema = new Schema(
  {
    location: {
      type: { type: String, enum: ['Point'], default: 'Point' },
      coordinates: { type: [Number], index: '2dsphere' },
    },
    ratings: {
      type: mongoose.Mixed, // A mixed type object to handle ratings. Each star level is represented in the ratings object
      1: Number, //  the key is the weight of that star level
      2: Number,
      3: Number,
      4: Number,
      5: Number,
      default: { 1: 1, 2: 1, 3: 1, 4: 1, 5: 1 },
      // TODO:: refre https://plainenglish.io/blog/creating-a-product-rating-system-with-mongodb-and-node-js
      get: function (r) {
        // r is the entire ratings object
        let items = Object.entries(r); // get an array of key/value pairs of the object like this [[1:1], [2:1]...]
        let sum = 0; // sum of weighted ratings
        let total = 0; // total number of ratings
        for (let [key, value] of items) {
          total += value;
          sum += value * parseInt(key); // multiply the total number of ratings by it's weight in this case which is the key
        }
        return Math.round(sum / total);
      },
      set: function (r) {
        if (!(this instanceof mongoose.Document)) {
          // only call setter when updating the whole path with an object
          if (r instanceof Object) return r;
          else {
            throw new Error('');
          }
        } else {
          // get the actual ratings object without using the getter which returns  an integer value
          // r is the ratings which is an integer value that represent the star level from 1 to 5
          if (r instanceof Object) {
            return r; // handle setting default when creating object
          }
          this.get('ratings', null, { getters: false })[r] =
            1 + parseInt(this.get('ratings', null, { getters: false })[r]);
          return this.get('ratings', null, { getters: false });
        } // return the updated ratings object
      },
      validate: {
        validator: function (i) {
          let b = [1, 2, 3, 4, 5]; // valid star levels
          let v = Object.keys(i).sort();
          return b.every(
            (x, j) => v.length === b.length && x === parseInt(v[j])
          );
        },
        message: 'Invalid Star Level',
      },
    },
  },
  { timestamps: true, toObject: { getters: true }, toJSON: { getters: true } }
);

module.exports = mongoose.model('Address', AddressSchema);

and I'm trying to get the address with the below aggregation

  getAddressesWithinRange: async (lat, lng, range) => {
    const pipeline = [
      {
        $geoNear: {
          near: {
            type: 'Point',
            coordinates: [Number(lng), Number(lat)],
          },
          distanceField: 'distance',
          maxDistance: range,
          spherical: true,
        },
      },
    ];
    const addressesWithinRange = await Address.aggregate(pipeline);
    return addressesWithinRange;
  },

and I have

const addresses = getAddressesWithinRange(
    lat,
    lng,
    TWO_KM
  );

then I'm doing addresses[0].ratings then getting

{
"1": 0,
"2": 1,
"3": 1,
"4": 1,
"5": 0,
}

instead of the getter value which is 3

I tried everything but it's not working please help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant