0
# Node Operations
1
2
Complete CRUD operations for OpenStreetMap nodes including creation, retrieval, updating, deletion, history tracking, and relationship queries. Nodes represent point features in OpenStreetMap and are the fundamental building blocks for ways and relations.
3
4
## Capabilities
5
6
### Node Retrieval
7
8
Get individual nodes by ID with optional version specification.
9
10
```python { .api }
11
def NodeGet(NodeId, NodeVersion=-1):
12
"""
13
Returns node with NodeId as a dict.
14
15
Parameters:
16
- NodeId (int): Unique identifier of the node
17
- NodeVersion (int, optional): Specific version to retrieve (-1 for latest)
18
19
Returns:
20
dict: Node data including id, lat, lon, tag, changeset, version,
21
user, uid, timestamp, visible
22
23
Raises:
24
- ElementDeletedApiError: If node has been deleted
25
- ElementNotFoundApiError: If node cannot be found
26
"""
27
```
28
29
**Usage Example:**
30
31
```python
32
import osmapi
33
34
api = osmapi.OsmApi()
35
36
# Get latest version of node
37
node = api.NodeGet(123)
38
print(f"Node {node['id']} at ({node['lat']}, {node['lon']})")
39
print(f"Tags: {node['tag']}")
40
41
# Get specific version
42
node_v2 = api.NodeGet(123, NodeVersion=2)
43
print(f"Version 2 coordinates: ({node_v2['lat']}, {node_v2['lon']})")
44
```
45
46
### Node Creation
47
48
Create new nodes with coordinates and optional tags.
49
50
```python { .api }
51
def NodeCreate(NodeData):
52
"""
53
Creates a node based on the supplied NodeData dict.
54
55
Parameters:
56
- NodeData (dict): Node data with lat, lon, and optional tag
57
Required: lat (float), lon (float)
58
Optional: tag (dict)
59
60
Returns:
61
dict: Updated NodeData with assigned id, version, changeset,
62
user, uid, visible
63
64
Raises:
65
- UsernamePasswordMissingError: If no authentication provided
66
- NoChangesetOpenError: If no changeset is open
67
- OsmTypeAlreadyExistsError: If node data contains existing ID
68
- ChangesetClosedApiError: If changeset is closed
69
"""
70
```
71
72
**Usage Example:**
73
74
```python
75
import osmapi
76
77
api = osmapi.OsmApi(username="your_username", password="your_password")
78
79
# Create node with minimal data
80
with api.Changeset({"comment": "Adding new amenity"}) as changeset_id:
81
new_node = api.NodeCreate({
82
"lat": 47.6062,
83
"lon": -122.3321,
84
"tag": {
85
"name": "Seattle Center",
86
"amenity": "attraction",
87
"website": "https://www.seattlecenter.com"
88
}
89
})
90
print(f"Created node {new_node['id']} in changeset {changeset_id}")
91
```
92
93
### Node Updates
94
95
Modify existing nodes by updating coordinates, tags, or other attributes.
96
97
```python { .api }
98
def NodeUpdate(NodeData):
99
"""
100
Updates node with the supplied NodeData dict.
101
102
Parameters:
103
- NodeData (dict): Node data with id, version, and updated fields
104
Required: id (int), lat (float), lon (float), version (int)
105
Optional: tag (dict)
106
107
Returns:
108
dict: Updated NodeData with new version, changeset, user, uid, visible
109
110
Raises:
111
- UsernamePasswordMissingError: If no authentication provided
112
- NoChangesetOpenError: If no changeset is open
113
- VersionMismatchApiError: If version doesn't match current
114
- ChangesetClosedApiError: If changeset is closed
115
"""
116
```
117
118
**Usage Example:**
119
120
```python
121
import osmapi
122
123
api = osmapi.OsmApi(username="your_username", password="your_password")
124
125
# Get current node data
126
node = api.NodeGet(12345)
127
128
# Update tags
129
with api.Changeset({"comment": "Updating amenity information"}) as changeset_id:
130
node["tag"]["opening_hours"] = "Mo-Su 09:00-21:00"
131
node["tag"]["phone"] = "+1-206-684-7200"
132
133
updated_node = api.NodeUpdate(node)
134
print(f"Updated node {updated_node['id']} to version {updated_node['version']}")
135
```
136
137
### Node Deletion
138
139
Delete nodes from OpenStreetMap (marks as invisible).
140
141
```python { .api }
142
def NodeDelete(NodeData):
143
"""
144
Delete node with NodeData.
145
146
Parameters:
147
- NodeData (dict): Node data with id, version, and current attributes
148
Required: id (int), lat (float), lon (float), version (int)
149
Optional: tag (dict)
150
151
Returns:
152
dict: Updated NodeData with visible=False and new version
153
154
Raises:
155
- UsernamePasswordMissingError: If no authentication provided
156
- NoChangesetOpenError: If no changeset is open
157
- VersionMismatchApiError: If version doesn't match current
158
- ChangesetClosedApiError: If changeset is closed
159
- ElementDeletedApiError: If node already deleted
160
- ElementNotFoundApiError: If node cannot be found
161
"""
162
```
163
164
**Usage Example:**
165
166
```python
167
import osmapi
168
169
api = osmapi.OsmApi(username="your_username", password="your_password")
170
171
# Get node to delete
172
node = api.NodeGet(12345)
173
174
# Delete the node
175
with api.Changeset({"comment": "Removing obsolete node"}) as changeset_id:
176
deleted_node = api.NodeDelete(node)
177
print(f"Deleted node {deleted_node['id']}, now version {deleted_node['version']}")
178
print(f"Visible: {deleted_node['visible']}") # False
179
```
180
181
### Node History
182
183
Retrieve complete version history for a node.
184
185
```python { .api }
186
def NodeHistory(NodeId):
187
"""
188
Returns dict with version as key containing all node versions.
189
190
Parameters:
191
- NodeId (int): Unique identifier of the node
192
193
Returns:
194
dict: Version history with version numbers as keys and
195
NodeData dicts as values
196
"""
197
```
198
199
**Usage Example:**
200
201
```python
202
import osmapi
203
204
api = osmapi.OsmApi()
205
206
# Get complete history
207
history = api.NodeHistory(123)
208
209
for version, node_data in history.items():
210
print(f"Version {version}: {node_data['user']} at {node_data['timestamp']}")
211
print(f" Coordinates: ({node_data['lat']}, {node_data['lon']})")
212
print(f" Tags: {node_data['tag']}")
213
```
214
215
### Node Relationships
216
217
Find ways and relations that reference a specific node.
218
219
```python { .api }
220
def NodeWays(NodeId):
221
"""
222
Returns a list of ways containing the specified node.
223
224
Parameters:
225
- NodeId (int): Unique identifier of the node
226
227
Returns:
228
list[dict]: List of WayData dicts containing the node
229
"""
230
231
def NodeRelations(NodeId):
232
"""
233
Returns a list of relations containing the specified node.
234
235
Parameters:
236
- NodeId (int): Unique identifier of the node
237
238
Returns:
239
list[dict]: List of RelationData dicts containing the node
240
"""
241
```
242
243
**Usage Example:**
244
245
```python
246
import osmapi
247
248
api = osmapi.OsmApi()
249
250
node_id = 123
251
252
# Find ways using this node
253
ways = api.NodeWays(node_id)
254
print(f"Node {node_id} is used in {len(ways)} ways:")
255
for way in ways:
256
print(f" Way {way['id']}: {way['tag'].get('name', 'Unnamed')}")
257
258
# Find relations using this node
259
relations = api.NodeRelations(node_id)
260
print(f"Node {node_id} is used in {len(relations)} relations:")
261
for relation in relations:
262
print(f" Relation {relation['id']}: {relation['tag'].get('name', 'Unnamed')}")
263
```
264
265
### Bulk Node Operations
266
267
Retrieve multiple nodes in a single API call for efficiency.
268
269
```python { .api }
270
def NodesGet(NodeIdList):
271
"""
272
Returns dict with node IDs as keys for multiple nodes.
273
274
Parameters:
275
- NodeIdList (list[int]): List of node IDs to retrieve
276
277
Returns:
278
dict: Node IDs as keys with NodeData dicts as values
279
"""
280
```
281
282
**Usage Example:**
283
284
```python
285
import osmapi
286
287
api = osmapi.OsmApi()
288
289
# Get multiple nodes efficiently
290
node_ids = [123, 456, 789, 101112]
291
nodes = api.NodesGet(node_ids)
292
293
for node_id, node_data in nodes.items():
294
print(f"Node {node_id}: ({node_data['lat']}, {node_data['lon']})")
295
print(f" Tags: {node_data['tag']}")
296
297
# Process nodes that were found
298
found_ids = set(nodes.keys())
299
missing_ids = set(node_ids) - found_ids
300
if missing_ids:
301
print(f"Missing nodes: {missing_ids}")
302
```
303
304
## Node Data Structure
305
306
### NodeData Dictionary
307
308
```python { .api }
309
NodeData = {
310
'id': int, # Node ID (assigned by OSM after creation)
311
'lat': float, # Latitude in decimal degrees (required)
312
'lon': float, # Longitude in decimal degrees (required)
313
'tag': dict, # Key-value pairs for attributes
314
'version': int, # Version number (starts at 1)
315
'changeset': int, # ID of changeset that last modified this node
316
'user': str, # Username of last editor
317
'uid': int, # User ID of last editor
318
'timestamp': str, # ISO timestamp of last modification
319
'visible': bool # True if visible, False if deleted
320
}
321
```
322
323
### Common Node Tags
324
325
```python
326
# Point of Interest
327
{
328
"name": "Central Library",
329
"amenity": "library",
330
"opening_hours": "Mo-Fr 09:00-21:00; Sa 10:00-18:00",
331
"website": "https://library.example.com",
332
"wheelchair": "yes"
333
}
334
335
# Transportation
336
{
337
"name": "Main Street Station",
338
"public_transport": "stop_position",
339
"bus": "yes",
340
"ref": "123"
341
}
342
343
# Geographic feature
344
{
345
"name": "Mount Example",
346
"natural": "peak",
347
"ele": "1234",
348
"source": "GPS survey"
349
}
350
```
351
352
## Error Handling
353
354
Node operations can raise various exceptions based on different scenarios:
355
356
```python
357
import osmapi
358
359
api = osmapi.OsmApi()
360
361
try:
362
node = api.NodeGet(999999)
363
except osmapi.ElementNotFoundApiError:
364
print("Node does not exist")
365
except osmapi.ElementDeletedApiError:
366
print("Node has been deleted")
367
368
try:
369
with api.Changeset({"comment": "Test"}) as changeset_id:
370
api.NodeCreate({"lat": 0, "lon": 0, "tag": {}})
371
except osmapi.UsernamePasswordMissingError:
372
print("Authentication required for creating nodes")
373
except osmapi.VersionMismatchApiError:
374
print("Version conflict - node was modified by another user")
375
```