Uploaded image for project: 'Documentation'
  1. Documentation
  2. DOCS-14337

Map-Reduce Examples Docs Page - wrong or misleading examples

    XMLWordPrintableJSON

Details

    Description

      Description

      One of the freelancer writers that is writing an article for the SEO-Hygiene initiative (Content Marketing & Growth Teams) got stuck on writing some sample code examples with Node.js driver for the example of using MongoDB mapReduce.
       
      My team, Developer Advocate team, notice a couple things on the reference documentation that needs to be more clear:

      • in JS in general array.sum does not look correct, it should be array.reduce

       


      For Context the thread of the email of the freelancer writer:

      At any rate, back to the issues with mapReduce; I attempted to run the following code:

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values)
              }
          )
      """

      According to the Node driver's .d.ts files, this is valid usage. However, I got the error:

      """
      TypeError: Cannot read property 'out' of undefined
          at Collection.mapReduce
      """

      So, looking back at the docs page, I saw that there was a string assigned to "out":

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values)
              },
              {
                  out: "Test"
              }
          )
      """

      Not only did I get errors from typescript saying that "out" needed to be an object, I got the same error as before.

      However, with some searching online, I found that you're able to change the last config object to:

      """
      {
      out: { inline: 1 }
      }
      """

      Once I did this, I got an array of values, without commas, not combined in any way, returned to the console.

      Code:

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values);
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      Output (shortened):

      """
      [{"_id":1,"value":"NumberDecimal(\"1863.46\")NumberDecimal(\"798.25\")NumberDecimal(\"756.90\")NumberDecimal(\"758.22\")NumberDecimal(\"233.58\")NumberDecimal(\"122.05\")NumberDecimal(\"1628.90\")NumberDecimal(\"355.79\")NumberDecimal(\"1200.78\")NumberDecimal(\"719.72\")
      """

      Not knowing how Array.sum works (it's not valid JS, but it's documented as the way to combine an array of numbers from the docs page), I decided to use `values.reduce` to manually add the numbers together:

      """
       await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return values.reduce((p: number, c: any) => p + c, 0)
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      However, I ended up just getting `0` as a string appended at the start

      """
      [{"_id":1,"value":"0NumberDecimal(\"1863.46\")NumberDecimal(\"798.25\")NumberDecimal(\"756.90\")NumberDecimal(\"758.22\")NumberDecimal(\"233.58\")
      """

      I then decided to try and get the value of `NumberDecimal`.

      I tried using `parseInt` on `c`, which left me with `0` as a final result. I assume this is because `parseInt(Object)` is `NaN`

      The only way I was able to get the results of the numbers combined was the following code:

      """
       await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return values.reduce((p: number, c: any) => p + Number(JSON.parse(JSON.stringify(c))["$numberDecimal"], 0)
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      However, this seems like an obvious anti-pattern and I wouldn't feel comfortable putting this as official docs that I wrote.

      Just to make sure this wasn't a bug in the NodeJS driver, I attempted to use the Mongo Shell:

      """
      use("sample_supplies");

      db.sales.mapReduce(
          function() {
              emit(1, this.itemsTotal)
          },
          function(key, values) {
              return values.reduce((p, c) => p + c, 0)
          },
          {
              out: { inline: 1 }
          }
      )
      """

      And ran into the same issues as before (I tried all of the code variations I outlined for NodeJS as well with the same results)

       

      Scope of changes

      Impact to Other Docs

      MVP (Work and Date)

      Resources (Scope or Design Docs, Invision, etc.)

      Attachments

        Activity

          People

            Unassigned Unassigned
            r.rodrigues@mongodb.com Rita Martins Rodrigues (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              1 year, 14 weeks, 2 days ago