6
$\begingroup$

It is a nice thing that, if you have a data as a list of rules (even nested), Mathematica can export them in JSON format. After generating useful data in Mathematica, Therefore, it seems it ought to simple to export the results as JSON and call `mongoimport' to send it to MongoDB.

Unfortunately, there is a small gap between Mathematica and MongoDB. It is definitely not the fault of Mathematica. JSON is a free-form format. There is nothing wrong that Mathematica pretty-printing the JSON file with indents. However, mongoimport, requires that the format be "one block of JSON per line".

I can use very tedious codes to convert the nested list of rules into JSON acceptable to mongoimport. I have not run into mistakes by far, but I do not believe that my (ugly and complicated) code will always work for even more complicated data. Besides, it is simply not elegant.

Does anyone have an idea of how I could easily ask Mathematica to export ny data one record per line?

The following is one simple example of my list of rules.

{"C code" -> "cpd:C00003", 
"Name" -> {"NAD+", "NAD", "Nicotinamide adenine dinucleotide", "DPN",
  "Diphosphopyridine nucleotide", "Nadide", "beta-NAD+"}}

=========================================

The solution of using "Compact" option while exporting JSON will turn the whole file into a single line. This is not what I (MongoDB, in fact) want, either. But, compact or not, the following simple program can work as a pipeline to convert it into the "one-record-per-line" format. Hope that this will help some other people with similar demand. I am sorry that this is not a Mathematica code/solution. But it serves to link better between Mathematica and MongoDB.

#include <iostream>

int main(int argc, const char * argv[]) {
    char curc = ' ';
    int kdepth = 0;

    do {
        std::cin.get(curc);
        if( kdepth == 0 ) {
            if( curc == '{') {
                std::cout << curc;
                ++kdepth;
            }
        } else {
            switch(curc) {
                case '{':
                    ++kdepth;
                    break;
                case '}':
                    --kdepth;
                    break;
                case '\n':
                case '\t':
                    curc = ' ';
                    break;
            }
            std::cout.put(curc);
            if( curc == '}' && kdepth == 0 ) {
                std::cout << std::endl;
            }
        }
    } while( !std::cin.eof() );
    return 0;
}
$\endgroup$
  • 2
    $\begingroup$ have you tried ExportString[data, "JSON", "Compact" -> True]? It is the only documented option for "JSON" export format and seems to do what you want... $\endgroup$ – Albert Retey Mar 3 '15 at 9:46
  • $\begingroup$ Thank you! Albert. It really makes the difference. However, the whole list of records was output to the file as one line. In my case, there are more than 17000 of records like the one I showed. I wrote a C++ program to parse the output file which put one record in one line. It works for this "all-in-one-line" output file, too. Later I will post my code. Thanks again! $\endgroup$ – 梁國淦 Mar 4 '15 at 12:22
2
$\begingroup$

Wolfram Language 11.3 now has support for interfacing with MongoDB.

Using this package to directly insert to and read from MongoDB is recommended.

However, if you still want a Mongo JSON representation of a WL expression along with BSON type annotations, MongoLink has some internal functionality that you might find useful. For example:

In[82]:= << MongoLink`
a = <|"a" -> DateObject[], "b" -> Null, "c" -> {1, <|"k" -> True|>}, 
   "d" -> ByteArray[{1, 2}]|>;
BSONToJSON[ToBSON@a]


Out[84]= "{ \"a\" : { \"$date\" : { \"$numberLong\" : \"1520944211417\
\" } }, \"b\" : null, \"c\" : [ { \"$numberInt\" : \"1\" }, { \"k\" : \
true } ], \"d\" : { \"$binary\" : { \"base64\": \"AQI=\", \"subType\" \
: \"00\" } } }"
$\endgroup$
  • $\begingroup$ Thank you very much. I saw the announcement of 11.3 but I have not taken the time to upgrade yet. Now there is a good reason to do that. $\endgroup$ – 梁國淦 Mar 26 '18 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.