Skip to main content

The MongoDB Writer for fme currently does not support writing to the MongoDB array data type. I am trying to develop a workflow in fme that can write to a JSON array data type in MongoDB when the number of objects in a json array are not fixed, for example (see "alternateNames array"):

{
    "geonameId" : 3,
    "name" : Toronto,
    "alternateNames" : 3 
        {   
    "alternateName" : "Toronto",
            "isoLanguage" : "af"
        }, 
        {
            "alternateName" : "Toronto",
            "isoLanguage" : "fa"
        }
    ]
}

 


in another record from the source, this "alternateNames" array might be contain more objects:

{
    "geonameId" : 1859924,
    "name" : Kashiwa,
    "alternateNames" : e 
        {   
    "alternateName" : "Kashiwa",
            "isoLanguage" : "eng"
        }, 

   {   
    "alternateName" : "Ka?iva",
            "isoLanguage" : "eng"
        }, 
        {
            "alternateName" : ??????,
            "isoLanguage" : "ar"
        }
    ]
}

 

If there is only one object in the array, I know I can use the JSONFlattener to format it so it will write to the MongoDB writer as an array (see example below). Unfortunately, this workflow does not work if the objects in the array is > 1.

 

0684Q00000ArF99QAF.jpg

The source data loaded into FME, it looks like this: 

Attribute NameAttribute ValuegeonameId6167865nameTorontoAlternateNames {"alternateName":"Toronto","isoLanguage":"af"},{"alternateName":"Toronto","isoLanguage":"ang"}]

Hi adriano_n90, have you tried writing the data as a list attribute?

That does have a limitation though: you can't write object arrays, only arrays of numbers, booleans, strings, etc.

For example you could have a list attribute like:

my_list{0}: "a"
my_list{1}: "b"
my_list{2}: "c"

and it should be written as JSON like:

{
   "my_list": S
      "a",
      "b",
      "c"
   ]
}

However, we presently can't make something like:

{
   "my_object_list": t
      { "name": "a" },
      { "name": "b" },
      { "name": "c" }
   ]
}

One way to work around this is with a `JSONTemplater`. Set the MongoDB writer feature type parameter `Advanced > Document Source` to  `JSON Attribute` and then write the JSON you created in an attribute with the `JSONTemplater`.


Hi adriano_n90, have you tried writing the data as a list attribute?

That does have a limitation though: you can't write object arrays, only arrays of numbers, booleans, strings, etc.

For example you could have a list attribute like:

my_list{0}: "a"
my_list{1}: "b"
my_list{2}: "c"

and it should be written as JSON like:

{
   "my_list": S
      "a",
      "b",
      "c"
   ]
}

However, we presently can't make something like:

{
   "my_object_list": t
      { "name": "a" },
      { "name": "b" },
      { "name": "c" }
   ]
}

One way to work around this is with a `JSONTemplater`. Set the MongoDB writer feature type parameter `Advanced > Document Source` to  `JSON Attribute` and then write the JSON you created in an attribute with the `JSONTemplater`.

I don't think this will work with the JSONTemplater because the number of objects in the array will not be the same depending on the record. With the JSONTemplater, I believe I have to hardcore each key so that won't work if the number of objects change for each record. Also, This is just 1 of many arrays in this json document of a few for this record but the others don't have multiple objects per array.

 

0684Q00000ArMXMQA3.jpg

 


Hi @adriano_n90, for example, what attributes (pairs of attribute name and value) do you need to create from this JSON document?

{
    "AlternateNames" :  
        {
            "alternateName":"Toronto",
            "isoLanguage":"af"
        },
        {
            "alternateName":"Toronto",
            "isoLanguage":"ang"
        }
    ]
}

Something like this?

Attribute NameAttribute ValueafNameTrontoangNameTronto

Hi @adriano_n90, for example, what attributes (pairs of attribute name and value) do you need to create from this JSON document?

{
    "AlternateNames" :  
        {
            "alternateName":"Toronto",
            "isoLanguage":"af"
        },
        {
            "alternateName":"Toronto",
            "isoLanguage":"ang"
        }
    ]
}

Something like this?

Attribute NameAttribute ValueafNameTrontoangNameTronto

 

Hi @takashi, I would like
to keep both objects in the array when writing to mongo. 

 



The raw data per
record when read into fme looks like this:

 

(keep in mind the number of objects in the Attribute Name "AlternateNames" can change depending on each record).

 

 




 
  
  Attribute Name
  
  Attribute Value
 
  
  geonameId
  
  6167865

 


  
 
  
  name
  
  Toronto
 
  
  AlternateNames
  
  r{"alternateName":"Toronto","isoLanguage":"af"},{"alternateName":"Toronto","isoLanguage":"ang"}]

 

I would like the format written in MongoDB to be formated like this:
{
    "geonameId" : 3,
    "name" : Toronto,
    "alternateNames" : n 
        {   
    "alternateName" : Toronto,
            "isoLanguage" : "af"
        }, 
        {
            "alternateName" : Toronto,
            "isoLanguage" : "fa"
        }
    ]
}

 


Hi @adriano_n90, for example, what attributes (pairs of attribute name and value) do you need to create from this JSON document?

{
    "AlternateNames" :  
        {
            "alternateName":"Toronto",
            "isoLanguage":"af"
        },
        {
            "alternateName":"Toronto",
            "isoLanguage":"ang"
        }
    ]
}

Something like this?

Attribute NameAttribute ValueafNameTrontoangNameTronto
OK. The JSONTemplater with this expression might help you. Be aware the difference between the "fme:get-attribute" function and the "fme:get-json-attribute" function.

 

{
    "geonameId" : xs:integer(fme:get-attribute("geonameId")),
    "name" : fme:get-attribute("name"),
    "altenateNames" : fme:get-json-attribute("AlternateNames")
} 

OK. The JSONTemplater with this expression might help you. Be aware the difference between the "fme:get-attribute" function and the "fme:get-json-attribute" function.

 

{
    "geonameId" : xs:integer(fme:get-attribute("geonameId")),
    "name" : fme:get-attribute("name"),
    "altenateNames" : fme:get-json-attribute("AlternateNames")
} 
Yes! this solution that worked perfectly! I didn't even know this function existed. This function should be highlighted in the mongodb writer as a workaround to not being able to write to arrays through the MongoDb Writer. Thanks so much Takashi! 

 

 


Reply