Giter Club home page Giter Club logo

node-red-contrib-mongodb2's Introduction

node-red-contrib-mongodb3

MongoDB node driver 3.0 interface for Node-RED

based on node-red-bluemix-nodes and MongoDB 3 Driver

Please refer to the mongoDB node driver 'Collection' documentation to read about each operation.

Usage

msg.payload -

  • To pass a single parameter to an operation use msg.payload as your parameter (eg {_id: 1243})
  • To pass multiple parameters to an operation fill msg.payload with an array
  • If you want to pass a single parameter WHICH IS AN ARRAY (eg as with InserMany), wrap your array in an outer array: msg.payload = [[{_id: 1243}, {_id: 2345}]]

Passing the last operation parameter (callbak) is not supported, and will be stripped if provided.

URI - Using a single URI field allows you to specify Host, Port and Database configuration as well as all other features that are supported by the MongoClient.connect, such as Mongos Proxy Connection and Replicaset Server Connection - more information can be found here. Notice that the Username & Password fields did remain. They will still be saved as Node-RED credentials (i.e. kept private). If the Username is not empty or the Password is not empty, they will be escaped and added the the URI after the mongodb:// prefix (separated by ':' and with a '@' after them). You can also leave these fields empty and enter the credentials directly in the URI, following the standard syntax: mongodb://youruser:[email protected]:27017,host2.yourmongoprovider.com:27017/yourdb?replicaSet=foo. Do not enter your credentials both in the URI and the Username & Password fields - this will create an invalid URI such as: mongodb://youruserfromfield:yourpasswordformfield@youruserfromuri:[email protected]:27017,host2.yourmongoprovider.com:27017/yourdb?replicaSet=foo.

specifying authentication database - most recent deployments of mongoDB store user credentials in a separate databse (usually admin) rather than allongside the data in each Db. Therefore you will likley need to provide a authSource parameter in your URI eg: mongodb://host1.yourmongoprovider.com:27017/yourdb?ssl=true&authSource=admin&replicaSet=foo

Parallelism Limit - Sending a lot of commands in a short time to the underlying mongodb-native driver, without waiting for their response, may cause serious problems and slow down the whole app. This has probably something to do with the connection sockets being clogged and their cache getting filled. This option allows to limit the number of operations that are sent before getting a response. For example, if the parallelism-limit is set to 5 and we are making 7 operations in a short period of time, the first 5 operations will start immediately, but the 6th and 7th operations will wait in a queue. The 6th operation will start only when one of the first 5 operations has finished. Similarly, the 7th operation will start only when another operation has finished.

db & collection operations - These operations will simply pass the db/collection instance, so they can be used directly (for example, in function nodes). The db instance is the same one that node-red-contrib-mongodb3 caches and shares between all relevant nodes - if you disconnect it, all the other mongodb3 nodes will fail. Furthermore, the parallelism-limit does not consider the future operations that you will do with the db/collection instances. However, if there are many parallel operations, requesting the db/collection will block until some of these operations finish.

Change Log

2.0

BREAKING CHANGES : driver response props are now (correctly) added to message.payload, thus chaning the response shape see #34

1.0 message shape:

msg
|_  payload
     |_ ok
     |_ n
     |_ opTime
     |_ electionId     
     |_ operationTime
     |_ "$clusterTime

2.0 message shape (example for find()):

msg
|_  payload
     |_ insertedCount
     |_ ops
     |_ insertedIds      
     |_ result
            |_ ok
            |_ n
            |_ opTime
            |_ electionId
            |_ operationTime
            |_ "$clusterTime

Original creation 1.0.0

MongoDB 3 driver is originally based on MongoDB 2 driver node for Node-RED, and therefore is placed in the same github repository: (https://github.com/ozomer/node-red-contrib-mongodb2) The very-similar MongoDB 2 driver is in the same git repository, under the node-red-contrib-mongodb2 branch (not the master branch).

node-red-contrib-mongodb2's People

Contributors

igor-levkov avatar igors-levkovs avatar jomel avatar ozomer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

node-red-contrib-mongodb2's Issues

MongoDB generated ID

Hello, I am using node-red-contrib-monggodb3 and having troubles to pass an ObjectId as an argument, not being able to use a MongoDB auto-generated _id, is there any way to use "_id": 'ObjectId("myID")' as an argument?
I.E
I have the following document in my collection:

{
    "_id" : ObjectId("5c9156c7f8c3ec3259454571"),
    "name" : "teste_site_1",
}

If I pass as msg.payload to findOne Operation

msg.payload = {"name":"teste_site_1"}

returns my document without ObjectID in _id

{
    "_id" : "5c9156c7f8c3ec3259454571",
    "name" : "teste_site_1",
}

if I pass the _id as agument:

msg.payload = {"name":"teste_site_1"}

returns empty.
I can not call ObjectId in node-red and also cannot pass as string ObjectId.

Is this a bug or am I missing something?

ObjectId is not defined

Thanks for this great Mongo V3 node @ozomer! One question though, have you seen the Mongo find problem where:

msg.payload = { "_id": ObjectId("5bb59066e7179a6602f38d4e") } 

Debug Console --> "ReferenceError: ObjectId is not defined"

I'm having the same trouble. I've tried stringifying the value:

{ "_id": "ObjectId(\"5bb59066e7179a6602f38d4e\")" } 

as well omitting the ObjectId: { "_id": "5bb59066e7179a6602f38d4e" }

Any suggestions?

PS. installing node-red-contrib-objectid didn't help.

Projection document using mongodb3?

Hi!

Im switching from the mongodb2- to mongodb3 node. Using the following code to return specific fields (x_data) from my documents:

msg.collection="data"; msg.operation="findOne"; msg.payload=[{_id: "id123"}, {x_data: 1}];

Works as expected using the mongodb2-node, but the same code returns the whole document when using the mongodb3 node.

Any thoughts on this? Thanks

aggregate.toArray not working as expected

I checked npm and I'm using version 0.2.2.

I am able to get this working using the collection operation on the mongodb2 node and it returns 3 records as expected.

When I try the same aggregate using Dynamic (msg.operation) aggregate.toArray I get output that looks similar to find.toArray and no aggregation looks to be happening. The payload array objects have the original columns rather than the ones defined in the aggregate group and all records in the collection are returned.

Working using collection operation

 var coll = msg.payload;
 var agr = coll.aggregate([
     { $sort: { date: 1}},
     { $group: { 
         _id: '$topic',
         value: { $last: "$value"},
         lastDoc: { $last: "$_id"}
     } }
 ]).toArray(function(err, results) {
     var newMsg = {};

     results.forEach(function(result) {
        var time = result.lastDoc.getTimestamp()
        time.setHours(time.getUTCHours() - 6);
        newMsg[result._id] = {
            value: result.value,
            time: time.toLocaleString()
        };
     });

     node.send(newMsg);
 });

Not working Dynamic (msg.operation)

var newMsg = {};
newMsg.operation = 'aggregate.toArray';
newMsg.collection = 'temps';
newMsg.payload = [
    { $sort: { date: 1}},
    { $group: { 
        _id: '$topic',
        value: { $last: "$value"}
    } }
];
return newMsg;

handler function

var newMsg =[];
for (var i = 0; i < msg.payload.length; i++) {
    var item = {};
    var time = msg.payload[i].lastDoc.getTimestamp()
    time.setHours(time.getUTCHours() - 6);
    item[msg.payload[i]._id] = { 
        value: msg.payload[i].value,
        time: time.toLocaleString()
    };
    newMsg.push(item);
};
return  {payload: newMsg};

Find operation using msg.payload

Hello there,
I was wondering if you could check and see why the "find" operation is not supported. The "findOne" operation gently returns the value but it is not the case for "find":
What I am deploying for "find" is:
//
msg.collection = "Collection_1"
msg.operation = "find";
msg.payload = {'Name' : 'John'};
msg.limit = 2;
msg.sort = {"_id":-1}
return msg;
//
error message: "No operation defined"
//
or even if you have an alternative solution? sharing it it is much appreciated.

User and password from a message

Hello, sorry for the bothering, is it possible to take the connection options (e.g. user and password) from a message sent by a previous node?

Thanks
Carlo

Using Watch command.

Hi there, trying to use the watch command,

msg.collection="jobs";
msg.operation="watch";
var pipeline = null;
var options ={
fullDocument:"default"
};
msg.payload = [pipeline,options];
return msg;

im getting error
"TypeError: Cannot create property 'readPreference' on number '1542372194371'"

Any ideas? Thanks!

Username is preceeded with "/"

Hi there,

When I type in my authentication details, my username is proceeded with "/". In this example, my username to the database is pirobot

Version details
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]

Remote server mongod.log file (doing the write)
2016-06-02T11:37:33.125+0100 I NETWORK [initandlisten] connection accepted from 192.168.0.5:40017 #5 (1 connection now open)
2016-06-02T11:37:37.539+0100 I ACCESS [conn5] SCRAM-SHA-1 authentication failed for /pirobot on testiot from client 192.168.0.5 ; UserNotFound: Could not find user /pirobot@testiot
2016-06-02T11:37:39.375+0100 I NETWORK [conn5] end connection 192.168.0.5:40017 (0 connections now open)

I managed to get round the issue by renaming my user to "/pirobot" but it just seems a bit odd.

Any advice is appreciated, I am happy to provide more feedback.

Many thanks

Jason

How to not suppress _id

I'm trying to read data from one collection to another and need the object _ids to propagate. I can't get my find queries to return _ids. I looked at #8 to do this by setting {_id: 1} in the projection but it does not return the _id as well. Any ideas?

find.toArray, count & aggregate.toArray functions issues

Hi,

I am reporting three kind of problems.

The first is with the find.toArray function that returns an object insted of an array.

The second problem is with the count and countDocuments functions, which always return an empty object.

For the second problem I've tried different payloads but nothing changes, right now i am using the find.toArray, converting the result to an array and then using the .length to have the count result but it will be a problem because i will need to query big documents in a big collection just for a count.

The third problem is related to aggregate.toArray, which is not returning the same response that i recieve from robo3t with the same parameters.
For example even if i try an aggregate for the count problem, in which i put the match field and the $count operator, in mongo i am recieving the correct response meanwhile from the node I am recieving the entire list of the elements.

Thanks a lot

mongodb uri with mustache style

Hi there,

When I configure mongodb server uri, I need to put the uri as a string, like 'mongodb://localhost:27017'. But in my case, this uri will stay in a environment variable. In my settings.js I put the process.env values in the global context, then in a function box I get the environment variable value in the global context like this:

msg.mongoUri = context.global.env.MONGO_URI

So, is there a way to pass msg.mongoUri value to mongodb box uri field? If not, can I send you a pull request to make this possible using mustache style? It would be like this:

image

Best regards

Rafael

And by the way...sorry for my bad english skills.

deleting collection by ObjectID

I am not able to delete documents by "_id" using the deleteOne() method. I presume it's because I am passing the id as a string and not as an ObjectId object.
But saying that, how do I turn a string into an ObjectId object?

How to get the db or collection instance

Hi,

I'm having trouble to get the DB or collection instance; when I select the db or collection from the list where does it go? How can I get access to it?

Thanks,

Wesley

Isssue withe agregate method.

To reproduce the problem, you have just to follow the tutorial at : https://www.codeproject.com/Articles/1096142/MongoDB-Tutorial-Day-Aggregation

**1 Create the collection **

db.Student.insert({StudentName : "Vijay",Section : "A",Marks:70,Subject:["Hindi","English","Math"]})
db.Student.insert({StudentName : "Gaurav",Section : "A",Marks:90,Subject:["English"]})
db.Student.insert({StudentName : "Ajay",Section : "A",Marks:70,Subject:["Math"]})
db.Student.insert({StudentName : "Ankur",Section : "B",Marks:10,Subject:["Hindi"]})
db.Student.insert({StudentName : "Sunil",Section : "B",Marks:70,Subject:["Math"]})
db.Student.insert({StudentName : "Preeti",Section : "C",Marks:80,Subject:["Hindi","English"]})
db.Student.insert({StudentName : "Anuj",Section : "C",Marks:50,Subject:["English"]})
db.Student.insert({StudentName : "Palka",Section : "D",Marks:40,Subject:["Math"]})
db.Student.insert({StudentName : "Soniya",Section : "D",Marks:20,Subject:["English","Math"]})

**2 Run the following agregate from Node-red **

db.Student.aggregate ([
{
"$group":
{
"_id":
{
"Section" : "$Section"
},
"TotalMarks":
{
"$sum": "$Marks"
},
"Count":{ "$sum" : 1},
"Average" : {"$avg" : "$Marks"}
}
},
{
"$project" :
{
"SectionName" : "$_id.Section",
"Total" : "$TotalMarks"
}
},
{
"$sort":{"SectionName":-1}
},
{
"$limit" : 2
}
])

**3 if we use the mongodb node we have the good result : an Array of 2 entries **

[{"_id":{"Section":"D"},"SectionName":"D","Total":60},{"_id":{"Section":"C"},"SectionName":"C","Total":130}]

**4 if we use the mongodb2 node we do not have the good result : an Array of 4 entries. It looks like having the $limit operator ignored **

[{"_id":{"Section":"D"},"SectionName":"D","Total":60},{"_id":{"Section":"C"},"SectionName":"C","Total":130},{"_id":{"Section":"B"},"SectionName":"B","Total":80},{"_id":{"Section":"A"},"SectionName":"A","Total":230}]

mongodb2 trouble with group operation

When I send this command directly to mongodb or via robomongo, all is well and I see the expected results:

db.btnii.group(
   {
    keyf: function(doc) {
               return {time:"at "+doc._id.getTimestamp().getHours()+" on the "+doc._id.getTimestamp().getDate()+"th"}
           },
    cond: {"id":"sls-18446744073519651090"},
    reduce: function( curr, result ) {
               result.count++;
            },
    initial: { count: 0 },
    finalize: function(result) {

              }
   }
);

However, when I send this content to the mongodb2 group operation:

{ 
     keyf: function(doc) { 
               return {time:"at "+doc._id.getTimestamp().getHours()+" on the "+doc._id.getTimestamp().getDate()+"th"} 
           },
    cond: {"id":"sls-18446744073519651090"}, 
    reduce: function( curr, result ) { 
               result.count++; 
            }, 
    initial: { count: 0 }, 
    finalize: function(result) { 
              } 
   }

I see this error:

[error] [mongodb2 in:BTN-II mongodb2 group] TypeError: undefined is not a function

I've tried quite a few things and can't get this to work. Any suggestons? Is this an issue or an error on my part?

TypeError: Path must be a string. Received undefined

hello

i have been running node-red and use the mongodb2 node for while on nano pi neo air but when i run node-red with supervisor the node disappear and this the output of the log

Welcome to Node-RED
===================

1 Dec 14:41:34 - [info] Node-RED version: v0.17.5
1 Dec 14:41:34 - [info] Node.js  version: v6.9.2
1 Dec 14:41:34 - [info] Linux 3.4.39-h3 arm LE
1 Dec 14:41:36 - [info] Loading palette nodes
1 Dec 14:41:43 - [warn] ------------------------------------------------------
1 Dec 14:41:43 - [warn] [rpi-gpio] Info : Ignoring Raspberry Pi specific node
1 Dec 14:41:43 - [warn] [mongodb2] TypeError: Path must be a string. Received undefined
1 Dec 14:41:43 - [warn] ------------------------------------------------------
1 Dec 14:41:43 - [info] Settings file  : /home/pi/.node-red/settings.js
1 Dec 14:41:43 - [info] User directory : /home/pi/.node-red
1 Dec 14:41:43 - [info] Flows file     : /home/pi/.node-red/flows_NanoPi-NEO-Air.json
1 Dec 14:41:43 - [info] Creating new flow file
1 Dec 14:41:43 - [info] Starting flows
1 Dec 14:41:43 - [info] Started flows
1 Dec 14:41:43 - [info] Server now running at http://127.0.0.1:1880/

but if i run the node-red normally it appear again and no problem at all

i tried to re install node-red and reinstall mongodb2 node sudo since supervisor run in root mode but no luck

the node-js version i have test it on is :
latest
6.12.0
6.9.2

the os used on the nanopi neo air is the officel :
Distribution: Ubuntu 16.04.3 LTS
Kernel version: Linux 3.4.39-h3 armv7l

Using some sort and limit in msg.

Hello!

Can you explain how i can make some sort with mongodb2? In node-red-node-mongodb i just use simple case:

msg.payload = {};
msg.sort = { "_id": -1 };
msg.limit = 1;
return msg;

This return last one record from db.

Examples for msg.payload

Hi! I'm looking for examples in order to implement something like this:

var groups = {} // init group object
var currentGroupKey;
var groupInterval = 5 * 60 * 1000; // Five minutes in milliseconds

var cursor = db.collection("documents").find({}).sort({date: 1});

cursor.on('data', function(doc) {
  var timestamp = doc.date.getTime();

  if (currentGroupKey != null && currentGroupKey + groupInterval >= timestamp) {
    // add it to current group
    groups[currentGroupKey].push(doc);
  } else {
    // create a new group
    groups[timestamp] = [doc];
    currentGroupKey = timestamp;
  }
});
cursor.once('end', function() {
  // This is called after last document is read
  console.log(groups); // print your grouped documents
  db.close();
});

but I'm not able to find any examples on how to write the msg.payload. Could you please help me?

Many thanks,

Diego

get collections list

I would like to be able to get array with all collections in db. Could you add that operation?

msg.projection does not work

operation: find.toArray

The function before the mongodb3 node containts:

msg.payload = {"age":50}
msg.projection = {"firstName":1}

return msg;

Anyhow, the result includes all fields and not only the firstName like I wish.

Update

Hi I'm using this node with Node-Red v.0.18.7 and trying to update a document using the following function

var newMsg = msg;
newMsg.payload= {
query: { "imei": msg.payload.imei },
options : {upsert : true},
update: { $set: msg.payload }
};
return newMsg;

However nothing gets modified. Any idea?

Support for Environment Variables

I wanted to externalize the connection string for MongoDB as I have to run my flows on different setups/environments, but while referring to env variable as $(connectionString) it does not work.
node-red-node-mongodb node honors $( ) notation and the variables are replaced from environment variables if set. Is there something similar available for this node too ?

variable in payload message

Hi,
after different hours of research, I found how to make a find.toArray with projection:

msg.payload = [{timestamp: {$gt: date_from.getTime() , $lt: date_to.getTime() }},{"fields": { "name": 1,timestamp:1}}]

Now the problem is, if I want to substitute "name" with a variable?
How can I do? I tried:

msg.payload = [{timestamp: {$gt: date_from.getTime() , $lt: date_to.getTime() }},{"fields": { var: 1,timestamp:1}}]

but it doesn't work. Any idea?

Thanks

Lookup?

Is there a way to perform $lookup ? As I understand it, this is the equivalent of a JOIN in SQL. I am very new to MongoDB, so apologies in advance if this is off topic.

Does projection filter work with find.toArray ?

Hi,

Does .projection work with the find.toArray operation?

var myMsg = {}; 
myMsg.collection = 'sonde_int';
myMsg.operation = 'find.toArray';
myMsg.payload = {'subject': 'temp'};
myMsg.projection = {'value': 1 , '_id': 0};
myMsg.sort = {'timestamp': -1};
//For httpResponse 
myMsg.req = msg.reg; 
myMsg.res = msg.res; 
return myMsg ;

I read here node-mongodb

projection : Limits the fields to return for all matching documents.

My function always returns an array with all the fields. (even _id). Is it normal ?
I can always change the output like this with a new function :

var myMsg =[];
for (var i = 0; i < msg.payload.length; i++) {
myMsg .push(msg.payload[i].value) };
msg.payload = myMsg ;
return  msg;

But I would like to know if it was possible to limit the fields at the query level ?
Thanks in advance.

GeohaystackSearch or GeoFind Operation

Hello,

Could anyone help me to share a sample flow with Geohaystacksearch and Geofind operation?
I had created a document with geojson indexed field. I was able to apply geo filters like geowithin from the mongo query builder. I would like to do the same from mongodb2 node to expose the geospatial queries option as a rest interface.

Examples for Atlas?

Do you have any examples for connecting to a Mongodb in Atlas.

When I try to insert a document on 'test' I get the following error.
"MongoError: user is not allowed to do action [insert] on [test.$cmd]"

I assume it must be something to do with possibly needing some connection options but I'm not familiar with the format they need to be in and there are no hints in node-red in the info tab.

MongoDB3 trouble with InsertMany

Hi,

I´m having problems with the InsertMany method. I´m getting the error "MongoError: docs parameter must be an array of documents". I have tried putting the document array in the msg.payload and msg.payload.docs, but I'm always getting this error.
Any help is welcome!
Thanks!

msg.limit and msg.sort do not work with mongodb2

msg.limit and msg.sort do not work with mongodb2

example with msg.limit=2 , mongoDB2 retrieves 5 documents

13/11/2017 à 14:38:43node: d8581fa.e306e6
msg : Object
object
payload: array[5]
0: object
1: object
2: object
3: object
4: object
limit: 2
_msgid: "bea405f8.ccc488"

Helping hand with Inject Node

Hi,
I'm new to Node Red & Mongo, and am working on some IoT/Home Automation projects. Current;y I'm writing a few HomeAssistant sensors to MongoDB from MQTT > NodeRed > a few custom data changes > Mongo.

Now I'm trying to figure out how to get the data out of Mongo. I've been trying the other mongo nodes, but they won't let me use date & string functions so was hoping to use your node instead which looks like it will be much more flexible as it gives me access to the full mongoDB API.

I was wondering if you could provide an example of what I should pass into MongoDB2? I assume I should use the inject node, and put some API code in there? I just need some help starting me off.

Thx
JP

custom query

Hi,
i'm using your component "mongodb2" and "mongodb3". I'm having a problem to write this query:

db.collection.aggregate([{$match:{"id": {$eq: xxxxxx}}}, {"$group" : {_id:"$xxxxx", count:{$sum:1}}} ])

that works correctly in a mongo shell. But in your component there are only "aggregate.forEach" and "aggregate.toArray", but not only "aggregate". How can I resolve? Is there a possibility to put my query as string, directly?
Thanks

driver response props missing in message.payload

when running an operation like insertOne() the driver response incudes the following props:

  • insertedCount : The total amount of documents inserted.
  • ops : All the documents inserted using insertOne/insertMany/replaceOne.
  • insertedIds : Map of the index of the inserted document to the id of the inserted document.
  • connection : The connection object used for the operation.
  • result : The raw command result object returned from MongoDB
    -- ok
    -- n
    as per: http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~insertWriteOpResult

Therefore I expected my resulting message to look like:

msg
|_  payload
     |_ insertedCount
     |_ ops
     |_ insertedIds
      _(I am not expecting connection, as I know it is being explicitly removed, to save response sizes)_
     |_ result
            |_ ok
            |_ n

insted my resulting messge looks like:

msg
|_  payload
     |_ n
     |_ opTime
     |_ electionId
     |_ ok
     |_ operationTime
     |_ "$clusterTime

I think this is a bug in how the response in converted into the message....

Example

Hi,
very nice work. I am having trouble putting it to work. Is somewhere an example of a flow using your node?

Thanks

Pablo

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.