瀏覽代碼

Accelerate key-value queries

by examining the stringtable for each PrimitiveBlock before iterating
over the contained elements.
Johannes Hofmann 7 年之前
父節點
當前提交
b3149bc777
共有 1 個文件被更改,包括 55 次插入31 次删除
  1. 55
    31
      src/query.rs

+ 55
- 31
src/query.rs 查看文件

5
 
5
 
6
 pub trait Query {
6
 pub trait Query {
7
     type BI;
7
     type BI;
8
-    fn create_block_index(&self, &PrimitiveBlock) -> Self::BI;
8
+    fn create_block_index(&self, &PrimitiveBlock) -> Option<Self::BI>;
9
     fn node_matches(&self, &Self::BI, node: &Node) -> bool;
9
     fn node_matches(&self, &Self::BI, node: &Node) -> bool;
10
     fn dense_node_matches(&self, &Self::BI, dnode: &DenseNode) -> bool;
10
     fn dense_node_matches(&self, &Self::BI, dnode: &DenseNode) -> bool;
11
     fn way_matches(&self, &Self::BI, way: &Way) -> bool;
11
     fn way_matches(&self, &Self::BI, way: &Way) -> bool;
59
 impl Query for ValuePatternQuery {
59
 impl Query for ValuePatternQuery {
60
     type BI = ();
60
     type BI = ();
61
 
61
 
62
-    fn create_block_index(&self, _block: &PrimitiveBlock) -> () {
63
-        ()
62
+    fn create_block_index(&self, _block: &PrimitiveBlock) -> Option<()> {
63
+        Some(())
64
     }
64
     }
65
 
65
 
66
     fn node_matches(&self, _: &(), node: &Node) -> bool {
66
     fn node_matches(&self, _: &(), node: &Node) -> bool {
116
 }
116
 }
117
 
117
 
118
 impl Query for KeyValueQuery {
118
 impl Query for KeyValueQuery {
119
-    type BI = ();
119
+    type BI = (Vec<u32>, Vec<u32>);
120
+
121
+    fn create_block_index(&self, block: &PrimitiveBlock) -> Option<(Vec<u32>, Vec<u32>)> {
122
+        let mut key_indices = vec![];
123
+        let mut value_indices = vec![];
124
+
125
+        let key_bytes = self.key.as_bytes();
126
+        let value_bytes = self.value.as_bytes();
127
+
128
+        for (i, string) in block.raw_stringtable().iter().enumerate() {
129
+            if string.as_slice() == key_bytes {
130
+                key_indices.push(i as u32);
131
+            }
132
+            if string.as_slice() == value_bytes {
133
+                value_indices.push(i as u32);
134
+            }
135
+        }
136
+
137
+        if key_indices.is_empty() || value_indices.is_empty() {
138
+            // No matches possible for this block
139
+            return None;
140
+        }
120
 
141
 
121
-    fn create_block_index(&self, _block: &PrimitiveBlock) -> () {
122
-        ()
142
+        key_indices.sort();
143
+        value_indices.sort();
144
+
145
+        Some((key_indices, value_indices))
123
     }
146
     }
124
 
147
 
125
-    fn node_matches(&self, _: &(), node: &Node) -> bool {
126
-        for (key, val) in node.tags() {
127
-            if key == self.key && val == self.value {
148
+    fn node_matches(&self, bi: &Self::BI, node: &Node) -> bool {
149
+        for (key, val) in node.raw_tags() {
150
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
128
                 return true;
151
                 return true;
129
             }
152
             }
130
         }
153
         }
131
         return false;
154
         return false;
132
     }
155
     }
133
 
156
 
134
-    fn dense_node_matches(&self, _: &(), dnode: &DenseNode) -> bool {
157
+    fn dense_node_matches(&self, _bi: &Self::BI, dnode: &DenseNode) -> bool {
158
+        //TODO use raw tags
135
         for (key, val) in dnode.tags() {
159
         for (key, val) in dnode.tags() {
136
             if key == self.key && val == self.value {
160
             if key == self.key && val == self.value {
137
                 return true;
161
                 return true;
140
         return false;
164
         return false;
141
     }
165
     }
142
 
166
 
143
-    fn way_matches(&self, _: &(), way: &Way) -> bool {
144
-        for (key, val) in way.tags() {
145
-            if key == self.key && val == self.value {
167
+    fn way_matches(&self, bi: &Self::BI, way: &Way) -> bool {
168
+        for (key, val) in way.raw_tags() {
169
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
146
                 return true;
170
                 return true;
147
             }
171
             }
148
         }
172
         }
149
         return false;
173
         return false;
150
     }
174
     }
151
 
175
 
152
-    fn relation_matches(&self, _: &(), relation: &Relation) -> bool {
153
-        for (key, val) in relation.tags() {
154
-            if key == self.key && val == self.value {
176
+    fn relation_matches(&self, bi: &Self::BI, relation: &Relation) -> bool {
177
+        for (key, val) in relation.raw_tags() {
178
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
155
                 return true;
179
                 return true;
156
             }
180
             }
157
         }
181
         }
165
     matches: &mut Vec<LatLonDeg>,
189
     matches: &mut Vec<LatLonDeg>,
166
     way_node_ids: &mut Vec<i64>,
190
     way_node_ids: &mut Vec<i64>,
167
 ) {
191
 ) {
168
-    let block_index = query.create_block_index(block);
169
-
170
-    for node in block.groups().flat_map(|g| g.nodes()) {
171
-        if query.node_matches(&block_index, &node) {
172
-            let pos = LatLonDeg::new(node.lat(), node.lon());
173
-            matches.push(pos);
192
+    if let Some(block_index) = query.create_block_index(block) {
193
+        for node in block.groups().flat_map(|g| g.nodes()) {
194
+            if query.node_matches(&block_index, &node) {
195
+                let pos = LatLonDeg::new(node.lat(), node.lon());
196
+                matches.push(pos);
197
+            }
174
         }
198
         }
175
-    }
176
 
199
 
177
-    for node in block.groups().flat_map(|g| g.dense_nodes()) {
178
-        if query.dense_node_matches(&block_index, &node) {
179
-            let pos = LatLonDeg::new(node.lat(), node.lon());
180
-            matches.push(pos);
200
+        for node in block.groups().flat_map(|g| g.dense_nodes()) {
201
+            if query.dense_node_matches(&block_index, &node) {
202
+                let pos = LatLonDeg::new(node.lat(), node.lon());
203
+                matches.push(pos);
204
+            }
181
         }
205
         }
182
-    }
183
 
206
 
184
-    for way in block.groups().flat_map(|g| g.ways()) {
185
-        if query.way_matches(&block_index, &way) {
186
-            way_node_ids.push(way.refs_slice()[0]);
207
+        for way in block.groups().flat_map(|g| g.ways()) {
208
+            if query.way_matches(&block_index, &way) {
209
+                way_node_ids.push(way.refs_slice()[0]);
210
+            }
187
         }
211
         }
188
     }
212
     }
189
 }
213
 }